#include <sys_config.h>
#include <api/libosd/osd_lib.h>
#include <api/libosd/osd_common_draw.h>
#include "osd_lib_internal.h"

#ifndef __MM_OSD_VSRC_MEM_ADDR
#define __MM_OSD_VSRC_MEM_ADDR NULL
#endif
struct OSD_RscInfo	g_osd_rsc_info;
struct OSD_RegionInfo	g_osd_region_info;
struct OSD_SurfaceInfo	g_ge_surface_info;
PVSCR_LIST	 pVscrHead = NULL;
BOOL OSD_SwitchRegion(VSCR* pVscr,UINT32 new_color_mode);

extern VSCR 	g_vscr[];
//---------------------------- PRIVATE Parameter ----------------------------//
//---------------------------- PRIVATE FUNCTIONS ----------------------------//
#define C_MAX_OBJECT_RECORD     20
//#define DEO_VIDEO_QUALITY_IMPROVE
static UINT32 m_object_count;
static POBJECT_HEAD m_object_record[C_MAX_OBJECT_RECORD];
void add_object_record(POBJECT_HEAD obj)
{
#ifdef DEO_VIDEO_QUALITY_IMPROVE
    int i, pos;

	if(obj->pRoot != NULL)
        return;
    for(i=0, pos=-1; i<C_MAX_OBJECT_RECORD; i++)
    {
        if(m_object_record[i] == NULL && pos < 0)
            pos = i;
        if(m_object_record[i] == obj)
            break;
    }
    if(i >= C_MAX_OBJECT_RECORD)
    {
        m_object_record[pos] = obj;
        m_object_count++;
    }

     OSD_ShowOnOff(TRUE);
#endif
}

static void del_object_record(POBJECT_HEAD obj)
{
#ifdef DEO_VIDEO_QUALITY_IMPROVE
    int i;

	if(obj->pRoot != NULL)
        return;

    for(i=0; i<C_MAX_OBJECT_RECORD; i++)
    {
        if(m_object_record[i] == obj)
        {
            m_object_record[i] = NULL;
            m_object_count--;
        }
        if(m_object_record[i] != NULL)
        {
            if(OSD_RectInRect(&obj->frame, &(m_object_record[i]->frame)))
            {
                m_object_record[i] = NULL;
                m_object_count--;
            }
        }
    }
    
    
    if(!m_object_count)
    {
        OSD_ShowOnOff(FALSE);
    }
#endif
}

static void reset_object_record()
{
#ifdef DEO_VIDEO_QUALITY_IMPROVE
    m_object_count = 0;
    MEMSET(m_object_record, 0, sizeof(m_object_record));
#endif
}

UINT8 OSD_GetAdjacentObjID(POBJECT_HEAD pObj, VACTION action)
{
	if(action == VACT_CURSOR_UP)
		return pObj->bUpID;
	else if(action == VACT_CURSOR_DOWN)
		return pObj->bDownID;
	else if(action == VACT_CURSOR_LEFT)
		return pObj->bLeftID;
	else if(action == VACT_CURSOR_RIGHT)
		return pObj->bRightID;
	else
		return pObj->bID;
}

//---------------------------- PUBLIC FUNCTIONS -----------------------------//

BOOL OSD_RectInRect(const struct OSDRect* R,const struct OSDRect* r)
{
	if(r->uLeft >= R->uLeft && r->uTop>= R->uTop
		&& (r->uLeft + r->uWidth)<=(R->uLeft + R->uWidth)
		&& (r->uTop + r->uHeight)<=(R->uTop + R->uHeight))
		return TRUE;
	else
		return FALSE;
}

UINT8 OSD_GetShowIndex(const PCOLOR_STYLE pColorStyle, UINT8 bAttr)
{
    UINT8 *pStyle = (UINT8 *)pColorStyle;

    OSD_ASSERT(bAttr <= sizeof(COLOR_STYLE));
    if(bAttr)
        bAttr--;
    return pStyle[bAttr];
}

void OSD_GetRectsCross(const struct OSDRect *backR,const struct OSDRect *forgR, struct OSDRect* relativR)
{
	short ltx,lty,rbx,rby;
	short dw,dh;

	ltx = forgR->uLeft >=  backR->uLeft ? forgR->uLeft :  backR->uLeft;
	lty = forgR->uTop >=  backR->uTop ? forgR->uTop :  backR->uTop;
	rbx = (forgR->uLeft + forgR->uWidth) <= (backR->uLeft + backR->uWidth) ? (forgR->uLeft + forgR->uWidth) : (backR->uLeft + backR->uWidth);
	rby = (forgR->uTop + forgR->uHeight) <= (backR->uTop + backR->uHeight) ? (forgR->uTop + forgR->uHeight) : (backR->uTop + backR->uHeight);

	dw = rbx > ltx ? (rbx - ltx) : 0;
	dh = rby > lty ? (rby - lty) : 0;
	relativR->uWidth  = dw;
	relativR->uHeight = dh;
	relativR->uLeft = ltx;
  	relativR->uTop  = lty;	
}

lpVSCR OSD_DrawObjectFrame(struct OSDRect *pRect,UINT8 bStyleIdx)
{	
	VSCR* pGVscr;
	UINT32 bFlag;
	PWINSTYLE  lpWinSty;
	UINT32 style;
	
	lpWinSty = g_osd_rsc_info.osd_get_win_style(bStyleIdx);
	style = SST_GET_STYLE(lpWinSty->bWinStyleType);
		
	if(style == C_WS_USER_DEFINE)
		bFlag = OSD_GET_BACK;			
    else if((C_WS_LINE_DRAW == style)&& ( lpWinSty->wLeftLineIdx & C_NOSHOW )
        && ( lpWinSty->wTopLineIdx & C_NOSHOW )
        && ( lpWinSty->wRightLineIdx & C_NOSHOW )
        && ( lpWinSty->wBottomLineIdx & C_NOSHOW )
        && ( ( lpWinSty->wBgIdx & C_NOSHOW ) && !( lpWinSty->wBgIdx & C_MIXER) )
     )
        bFlag = OSD_DIRDRAW;
    else
    {
        bFlag = OSD_REQBUF;
        if(lpWinSty->wBgIdx & C_MIXER)
            bFlag |= OSD_GET_BACK;
            
       if( (style==C_WS_LINE_CIRCL_DRAW 
                || style==C_WS_PIC_DRAW )
            && !( bFlag & OSD_GET_BACK)
        )
        bFlag |= OSD_GET_CORNER;
    }
    
    pGVscr = OSD_GetVscr(pRect, bFlag);

#ifdef FONT_1BIT_SUPPORT    
    if(!(lpWinSty->wBgIdx & C_MIX_BG))
#endif
    {
        OSD_DrawStyleRect(pRect,bStyleIdx,pGVscr);
    }

        
    return pGVscr;
}


//Find object
POBJECT_HEAD OSD_GetTopRootObject(POBJECT_HEAD pObj)
{
	while(pObj)
        pObj = pObj->pRoot;
    return pObj;
}

UINT8 OSD_GetFocusID(POBJECT_HEAD pObj)
{
	UINT8 id = 0;
	POBJECT_HEAD pFocusObj;
	OBJLIST *ol;
	CONTAINER *con;		
	
	switch(pObj->bType)
	{
	case OT_OBJLIST:
		ol = (OBJLIST*)pObj;
		if(ol->bListStyle & LIST_ITEMS_COMPLETE)
			pFocusObj = ol->pListField[ol->wCurPoint];
		else
			pFocusObj = ol->pListField[ol->wCurPoint - ol->wTop];
		id = pFocusObj->bID;		
		break;
	case OT_CONTAINER:
		con = (CONTAINER*)pObj;
		id = con->FocusObjectID;
		break;
	case OT_TEXTFIELD:	
	case OT_BITMAP:
	case OT_EDITFIELD:
	case OT_MULTISEL:
	case OT_PROGRESSBAR:
	case OT_SCROLLBAR:
	case OT_MULTITEXT:	 	
	case OT_LIST:
	case OT_MATRIXBOX:	 		 	
	case OT_ANIMATION:	 		 	
	default:
		;		 			
	}	
		
	return id;	
}

POBJECT_HEAD OSD_GetObject(POBJECT_HEAD pObj, UINT8 bID)
{
    if(!bID)
        return NULL;     
        
	UINT32 i,n;
	POBJECT_HEAD oh = NULL;
	OBJLIST *ol;
	CONTAINER *con;
	UINT16 cnt;
	
	switch(pObj->bType)
	{
	case OT_OBJLIST:		
		ol = (OBJLIST*)pObj;
		cnt = OSD_GetObjListCount(ol);
		for(i=0;i<cnt;i++)
		{
			oh = ol->pListField[i];
			if(oh!=NULL && oh->bID == bID)
				return oh;
		}
		break;
	case OT_CONTAINER:
		con = (CONTAINER*)pObj;
		oh = (POBJECT_HEAD )(con->pNextInCntn);
		while(oh!=NULL)
		{
			if(oh->bID == bID)
				return oh;
			oh = oh->pNext;
		}
		break;
	case OT_TEXTFIELD:	
	case OT_BITMAP:
	case OT_EDITFIELD:
	case OT_MULTISEL:
	case OT_PROGRESSBAR:
	case OT_SCROLLBAR:
	case OT_MULTITEXT:	 	
	case OT_LIST:
	case OT_MATRIXBOX:	 		 	
	case OT_ANIMATION:	 		 	
	default:
		;		 			
	}	
			
	return oh;
}

POBJECT_HEAD OSD_GetFocusObject(POBJECT_HEAD pObj)
{
	UINT8 bID;
	
	bID = OSD_GetFocusID(pObj);
	return OSD_GetObject(pObj,bID);
}

POBJECT_HEAD OSD_GetAdjacentObject(POBJECT_HEAD pObj, VACTION action)
{
	POBJECT_HEAD pBox;
	POBJECT_HEAD pNewObj;
	UINT8		 bNewId, bNextNewId,bCount=0;	// for safety control
	
	if(pObj == NULL)
		return NULL;
		
	pBox = pObj->pRoot;
	if(pBox == NULL)
		return NULL;
					
	bNextNewId = bNewId = OSD_GetAdjacentObjID(pObj,action);	

	while ((pObj->bID != bNewId) && ((bCount++)<255))
	{
		pNewObj = OSD_GetObject(pBox,bNewId);
		if(pNewObj == NULL)
			return NULL;
				
		//if(pNewObj->bAttr & C_ATTR_ACTIVE)  //bug
		if(OSD_CheckAttr(pNewObj,C_ATTR_ACTIVE))
			return pNewObj;
		else
		{ 
			bNextNewId = OSD_GetAdjacentObjID(pNewObj,action);
			if(bNewId != bNextNewId)
				bNewId = bNextNewId;
			else
				break;						
		}
	}
	
	return pObj;
}

PRESULT OSD_ChangeFocus(POBJECT_HEAD pObj, UINT16 bNewFocusID,UINT32 parm)
{
	PRESULT Result = PROC_LOOP;

	OBJLIST *ol;
	CONTAINER *con;		
	
	switch(pObj->bType)
	{
	case OT_OBJLIST:
		ol = (OBJLIST*)pObj;
		Result = OSD_ObjListChgFocus(ol,bNewFocusID,parm);
		break;
	case OT_CONTAINER:
		con = (CONTAINER*)pObj;
		Result = OSD_ContainerChgFocus(con, (UINT8)bNewFocusID,parm);
		break;
	case OT_TEXTFIELD:	
	case OT_BITMAP:
	case OT_EDITFIELD:
	case OT_MULTISEL:
	case OT_PROGRESSBAR:
	case OT_SCROLLBAR:
	case OT_MULTITEXT:	 	
	case OT_LIST:
	case OT_MATRIXBOX:	 		 	
	case OT_ANIMATION:	 		 	
	default:
		;
	}

	return Result;	
}

void OSD_MoveObject(POBJECT_HEAD pObj, short x, short y, BOOL IsRelative)
{
	OBJLIST *ol;
    CONTAINER* con;
    POBJECT_HEAD oh;
    short ShiftX, ShiftY,rx,ry;
    UINT32 i,n;
    
    if(IsRelative)
    {
        ShiftX = x;
        ShiftY = y;
        rx = x;
        ry = y;
    }
    else
    {
        ShiftX = x - pObj->frame.uLeft;
        ShiftY = y - pObj->frame.uTop;
        rx = ShiftX;
        ry = ShiftY;

    }

    switch(pObj->bType)
    {
	case OT_OBJLIST:
        ol = (OBJLIST*)pObj;
        if(ol->bListStyle & LIST_ITEMS_COMPLETE)
            n = ol->wCount;
        else
            n = ol->wDep;
        for(i=0;i<n;i++)
            OSD_MoveObject(ol->pListField[i],rx,ry,TRUE);            
        if(ol->pSelMarkObj != NULL)
            OSD_MoveObject(ol->pSelMarkObj,rx,ry,TRUE); 
        if(ol->scrollBar != NULL)
            OSD_MoveObject((POBJECT_HEAD)ol->scrollBar,rx,ry,TRUE);
		break;
	case OT_CONTAINER:
        con = (CONTAINER*)pObj;
        oh = con->pNextInCntn;
        while(oh)
        {
            OSD_MoveObject(oh,rx,ry,TRUE);
            oh = oh->pNext;
        }
		break;
	case OT_TEXTFIELD:	
	case OT_BITMAP:
	case OT_EDITFIELD:
	case OT_MULTISEL:
	case OT_PROGRESSBAR:
	case OT_SCROLLBAR:
	case OT_MULTITEXT:	 	
	case OT_LIST:
	case OT_MATRIXBOX:
	case OT_ANIMATION:	 		 	
        ;            
    }

    pObj->frame.uLeft += ShiftX;
    pObj->frame.uTop  +=  ShiftY;    
}
//////////////////////////////////////////////////////////////////////////////
// Object drawing functions
//////////////////////////////////////////////////////////////////////////////
void OSD_DrawObjectCell(POBJECT_HEAD pObj, UINT8 bStyleIdx,	UINT32 nCmdDraw)
{
	UINT32 vscr_idx;
	
	vscr_idx = osal_task_get_current_id();
	if((vscr_idx == OSAL_INVALID_ID) || (vscr_idx > OSD_DRAW_TASK_MAX))
		ASSERT(0);
	
	switch(pObj->bType)
	{
	case OT_TEXTFIELD:
		OSD_DrawTextFieldCell((PTEXT_FIELD)pObj,bStyleIdx,nCmdDraw);
		break;
	case OT_BITMAP:
		OSD_DrawBitmapCell((PBITMAP)pObj,bStyleIdx,nCmdDraw);
		break;
	case OT_EDITFIELD:
		OSD_DrawEditFieldCell((PEDIT_FIELD)pObj,bStyleIdx,nCmdDraw);
		break;
	case OT_MULTISEL:
		OSD_DrawMultiselCell((PMULTISEL)pObj,bStyleIdx,nCmdDraw);
		break;
	case OT_PROGRESSBAR:
		OSD_DrawProgressBarCell((PPROGRESS_BAR)pObj,bStyleIdx,nCmdDraw);
		break;
	case OT_SCROLLBAR:
		OSD_DrawScrollBarCell((PSCROLL_BAR)pObj,bStyleIdx,nCmdDraw);
		break;
	case OT_MULTITEXT:
		OSD_DrawMultiTextCell((PMULTI_TEXT)pObj, bStyleIdx,nCmdDraw);
		break;
	case OT_LIST:
		OSD_DrawListCell((PLIST)pObj, bStyleIdx,nCmdDraw);
		break;
	case OT_MATRIXBOX:
		OSD_DrawMatrixBoxCell((PMATRIX_BOX)pObj, bStyleIdx,nCmdDraw);
		break;
	case OT_OBJLIST:
		OSD_DrawObjectListCell((POBJLIST)pObj,bStyleIdx,nCmdDraw);
		break;
	case OT_CONTAINER:
		OSD_DrawContainerCell((PCONTAINER)pObj,bStyleIdx,nCmdDraw);
		break;
	case OT_ANIMATION:
		OSD_DrawAnimationCell((PANIMATION)pObj,bStyleIdx,nCmdDraw);
		break;
	default:
		;
	}

	if(g_vscr[vscr_idx - 1].lpbScr != NULL)
		g_vscr[vscr_idx - 1].updatePending = 1;

	if( !(nCmdDraw & C_DRAW_SIGN_EVN_FLG) && pObj->pRoot == NULL)
		OSD_UpdateVscr(&g_vscr[vscr_idx - 1]);
}

PRESULT OSD_DrawObject(POBJECT_HEAD pObj, UINT32 nCmdDraw )
{
	PRESULT Result;
	UINT32 drawType;
	UINT8  bStyleIdx;
	UINT32 msg;
	UINT32 vscr_idx;

	vscr_idx = osal_task_get_current_id();
	if((vscr_idx == OSAL_INVALID_ID) || (vscr_idx > OSD_DRAW_TASK_MAX))
		ASSERT(0);

	PWINSTYLE	lpWinSty = g_osd_rsc_info.osd_get_win_style(pObj->style.bShowIdx);

	OSD_SwitchRegion(&g_vscr[vscr_idx - 1], SST_GET_COLOR(lpWinSty->bWinStyleType));
    OSD_Draw_Recode_Ge_Cmd_Start();
	if(pObj->bAttr == C_ATTR_ACTIVE)
	{
		drawType = C_DRAW_TYPE_NORMAL;
		bStyleIdx = pObj->style.bShowIdx;
	}
	else if(pObj->bAttr == C_ATTR_INACTIVE)
	{
		drawType = C_DRAW_TYPE_GRAY;
		bStyleIdx = pObj->style.bGrayIdx;
	}    
	else// if(pObj->bAttr == C_ATTR_HIDDEN)
	{
		drawType = C_DRAW_TYPE_HIDE;
		//bStyleIdx = pObj->style.bShowIdx;
		bStyleIdx = 0;
	}


	OSD_SetDrawType(nCmdDraw,drawType);

	if(nCmdDraw & C_DRAW_SIGN_EVN_FLG)    
	{   	
		Result = OSD_ObjProc(pObj,(MSG_TYPE_EVNT<<16)|EVN_PRE_DRAW,drawType,nCmdDraw);
        
		if(Result != PROC_PASS)
		{
            OSD_Draw_Recode_Ge_Cmd_Stop();
			return Result;
		}
	}

	// TODO:  Draw Object
    add_object_record(pObj);
	if(drawType == C_DRAW_TYPE_NORMAL || drawType== C_DRAW_TYPE_GRAY)
		OSD_DrawObjectCell(pObj,bStyleIdx,nCmdDraw);
	else
		OSD_HideObject(pObj,nCmdDraw);    	


	if(nCmdDraw & C_DRAW_SIGN_EVN_FLG)
	{
		OSD_ObjProc(pObj,(MSG_TYPE_EVNT<<16)|EVN_POST_DRAW,drawType,nCmdDraw);
	}
    OSD_Draw_Recode_Ge_Cmd_Stop();
	return PROC_PASS;   
}

PRESULT OSD_TrackObject(POBJECT_HEAD pObj, UINT32 nCmdDraw )
{
	PRESULT Result;
	UINT32 drawType;
	UINT8  bStyleIdx;
    UINT32 vscr_idx;

	vscr_idx = osal_task_get_current_id();
	if(pObj->bAttr == C_ATTR_ACTIVE)
	{
		drawType = C_DRAW_TYPE_HIGHLIGHT;
		bStyleIdx = pObj->style.bHLIdx;
	}
	else
		return PROC_PASS;

    PWINSTYLE	lpWinSty = g_osd_rsc_info.osd_get_win_style(pObj->style.bShowIdx);

	OSD_SwitchRegion(&g_vscr[vscr_idx - 1], SST_GET_COLOR(lpWinSty->bWinStyleType));
    OSD_Draw_Recode_Ge_Cmd_Start();
	OSD_SetDrawType(nCmdDraw,drawType);		

	if(nCmdDraw & C_DRAW_SIGN_EVN_FLG)    
	{
		Result = OSD_ObjProc(pObj,(MSG_TYPE_EVNT<<16) |EVN_PRE_DRAW, drawType, nCmdDraw);
		if(Result != PROC_PASS)
		{
            OSD_Draw_Recode_Ge_Cmd_Stop();
			return Result;
        }
	}
    add_object_record(pObj);
	OSD_DrawObjectCell(pObj,bStyleIdx,nCmdDraw);	

	if(nCmdDraw & C_DRAW_SIGN_EVN_FLG)
	{
		OSD_ObjProc(pObj,(MSG_TYPE_EVNT<<16) |EVN_POST_DRAW,drawType,nCmdDraw);
	}
    OSD_Draw_Recode_Ge_Cmd_Stop();
	return PROC_PASS;
			
}

PRESULT OSD_SelObject(POBJECT_HEAD pObj, UINT32 nCmdDraw )
{
	PRESULT Result;
	UINT32 drawType;
	UINT8  bStyleIdx;
	
	if(pObj->bAttr == C_ATTR_ACTIVE)
	{
		drawType = C_DRAW_TYPE_SELECT;
		bStyleIdx = pObj->style.bSelIdx;
	}
	else
		return PROC_PASS;
		
	OSD_SetDrawType(nCmdDraw,drawType);
	OSD_Draw_Recode_Ge_Cmd_Start();	
	if(nCmdDraw & C_DRAW_SIGN_EVN_FLG)    
	{
		Result = OSD_ObjProc(pObj,(MSG_TYPE_EVNT<<16) | EVN_PRE_DRAW,drawType, nCmdDraw);
		if(Result != PROC_PASS)
		{
            OSD_Draw_Recode_Ge_Cmd_Stop();
			return Result;
		}
	}
    add_object_record(pObj);
	OSD_DrawObjectCell(pObj,bStyleIdx,nCmdDraw);	
    
	if(nCmdDraw & C_DRAW_SIGN_EVN_FLG)
	{
		OSD_ObjProc(pObj,(MSG_TYPE_EVNT<<16) | EVN_POST_DRAW,drawType, nCmdDraw);
	}
	OSD_Draw_Recode_Ge_Cmd_Stop();
	return PROC_PASS;
	
}

void	OSD_HideObject(POBJECT_HEAD pObj, UINT32 nCmdDraw )
{
	PRESULT Result;
	UINT32 drawType;
	UINT32 vscr_idx,dwColorIdx;
	OBJECT_HEAD* pBox;
	
	vscr_idx = osal_task_get_current_id();
	if((vscr_idx == OSAL_INVALID_ID) || (vscr_idx > OSD_DRAW_TASK_MAX))
		ASSERT(0);
	drawType= C_DRAW_TYPE_HIDE;
    OSD_Draw_Recode_Ge_Cmd_Start();
	if(nCmdDraw & C_DRAW_SIGN_EVN_FLG)    
	{
		Result = OSD_ObjProc(pObj,(MSG_TYPE_EVNT<<16) |EVN_PRE_DRAW,drawType, nCmdDraw);
		if(Result != PROC_PASS)
		{
            OSD_Draw_Recode_Ge_Cmd_Stop();
			return ;
		}
	}

	pBox = (OBJECT_HEAD*)(pObj->pRoot);
	if(pBox == NULL)
		OSD_ClearObject(pObj,nCmdDraw);
	else
	{					
		dwColorIdx = g_osd_rsc_info.osd_get_win_style(pBox->style.bShowIdx)->wBgIdx;	
		if(!(dwColorIdx & C_NOSHOW))
			OSD_DrawFrame(&pObj->frame, dwColorIdx, NULL);
		//OSDDrawSolidRectangle0(&vScr, &pObj->frame, C_NOSHOW, C_NOSHOW, C_NOSHOW, C_NOSHOW, dwColorIdx);
	}

	if(nCmdDraw & C_DRAW_SIGN_EVN_FLG)
	{
		OSD_ObjProc(pObj,(MSG_TYPE_EVNT<<16) |EVN_POST_DRAW,drawType, nCmdDraw);
	}
	else if(pObj->pRoot == NULL && pBox!=NULL)
	{
		if(g_vscr[vscr_idx -1].lpbScr != NULL)
			g_vscr[vscr_idx -1].updatePending = 1;
		
		OSD_UpdateVscr(&g_vscr[vscr_idx -1]);    
	}
    OSD_Draw_Recode_Ge_Cmd_Stop();
    
}


void  OSD_ClearObject(POBJECT_HEAD pObj, UINT32 nCmdDraw)
{
	PRESULT Result;
	UINT32 vscr_idx,drawType;
	VSCR* pVscr;
	
	vscr_idx = osal_task_get_current_id();
	if((vscr_idx == OSAL_INVALID_ID) || (vscr_idx > OSD_DRAW_TASK_MAX))
		ASSERT(0);
	drawType= C_DRAW_TYPE_HIDE;
    OSD_Draw_Recode_Ge_Cmd_Start();
	if(nCmdDraw & C_DRAW_SIGN_EVN_FLG)    
	{
		Result = OSD_ObjProc(pObj,(MSG_TYPE_EVNT<<16) |EVN_PRE_DRAW,drawType, nCmdDraw);
		if(Result != PROC_PASS)
		{   
            OSD_Draw_Recode_Ge_Cmd_Stop();
            return ;
		}
	}    

	pVscr = OSD_GetVscr(&pObj->frame, OSD_REQBUF);
	OSD_DrawFrame(&pObj->frame,OSD_GetTransColor(pVscr->bColorMode, TRUE),pVscr);
	pVscr->updatePending = 1;

	if(nCmdDraw & C_DRAW_SIGN_EVN_FLG)
	{
		OSD_ObjProc(pObj,(MSG_TYPE_EVNT<<16) |EVN_POST_DRAW,drawType, nCmdDraw);
	}
	else if(pObj->pRoot == NULL)
	{
		if(g_vscr[vscr_idx - 1].lpbScr != NULL)
			g_vscr[vscr_idx - 1].updatePending = 1;

		OSD_UpdateVscr(&g_vscr[vscr_idx - 1]);    
        del_object_record(pObj);
	}    
    OSD_Draw_Recode_Ge_Cmd_Stop();
	return;
}

BOOL OSD_ClearScreen2(void)
{
	OSD_RECT rect;
	UINT32 vscr_idx;
	VSCR *apVscr;

	vscr_idx = osal_task_get_current_id();
	apVscr = OSD_GetTaskVscr(vscr_idx);
    if (apVscr)
    {
        apVscr->updatePending = 0;
        apVscr->lpbScr = NULL;
    }

    /* Clear OSD */
	OSD_GetRectOnScreen(&rect);
	rect.uLeft = rect.uTop= 0;

	UINT32 trans_color = OSD_GetTransColor(g_osd_region_info.tOpenPara.eMode, TRUE);
	//OSDDrv_RegionFill32((HANDLE)g_osd_region_info.osddev_handle,0,&(g_osd_region_info.osdrect),trans_color);
	OSDLib_RegionFill(&rect, trans_color);
        reset_object_record();

    return TRUE;
}


//////////////////////////////////////////////////////////////////////////////
// Object common processing function
//////////////////////////////////////////////////////////////////////////////

PRESULT OSD_NotifyEvent(POBJECT_HEAD pObj, VEVENT Event, UINT32 Param1, UINT32 Param2)
{
    if(pObj->pfnCallback)
        return pObj->pfnCallback(pObj, Event, Param1, Param2);
    return PROC_PASS;
}

UINT8 evts_to_child[] = 
{
	EVN_FOCUS_PRE_LOSE,
	EVN_FOCUS_POST_LOSE,
	EVN_FOCUS_PRE_GET,
	EVN_FOCUS_POST_GET,	
};
#define EVT_TO_CHILD_NUM	(sizeof(evts_to_child))

UINT8 evts_to_childmap[][2] =
{
	{EVN_FOCUS_PRE_LOSE,	EVN_PARENT_FOCUS_PRE_LOSE},
	{EVN_FOCUS_POST_LOSE,	EVN_PARENT_FOCUS_POST_LOSE},
	{EVN_FOCUS_PRE_GET,	EVN_PARENT_FOCUS_PRE_GET},
	{EVN_FOCUS_POST_GET,		EVN_PARENT_FOCUS_POST_GET},
};
#define EVT_TO_CHILDMAP_NUM		(sizeof(evts_to_childmap)/2)

BOOL OSD_EventPassToChild(UINT32 msg,UINT32* submsg)
{
	UINT32 i,n;
	//UINT32 msgType,msgCode,subMsgCode;
	UINT32	subMsgCode;
	BOOL b = FALSE; 
	
	//msgType = OSD_GetOSDMessageType(msg);
	//subMsgCode = msgCode = OSD_GetOSDMessageCode(msg);
	
	subMsgCode = msg;
//	if(msgType == MSG_TYPE_EVNT)
//	{
		for(i=0;i<EVT_TO_CHILD_NUM;i++)
			if(msg == evts_to_child[i])
			{
				b = TRUE;
				break;
			}
			
		if(b)			
		{
			for(i=0;i<EVT_TO_CHILDMAP_NUM;i++)
				if(msg == evts_to_childmap[i][0])
				{
					subMsgCode = evts_to_childmap[i][1];
					break;
				}
		}
//	}
	
	if(b)
	{
		//*submsg = OSD_GetOSDMessage(MSG_TYPE_EVNT,subMsgCode);	
		*submsg =subMsgCode;
	}
	
	return b;		
}



PRESULT OSD_ObjOpen(POBJECT_HEAD pObj, UINT32 param)
{
	PRESULT Result;
	OBJECT_HEAD *pFoucsObj;
	UINT32 vscr_idx,nCmdDraw = 0;

	vscr_idx = osal_task_get_current_id();
	if((vscr_idx == OSAL_INVALID_ID) || (vscr_idx > OSD_DRAW_TASK_MAX))
		ASSERT(0);

	//PWINSTYLE	lpWinSty = g_osd_rsc_info.osd_get_win_style(pObj->style.bShowIdx);

	//OSD_SwitchRegion(&g_vscr[vscr_idx - 1], SST_GET_COLOR(lpWinSty->bWinStyleType));
		
	pFoucsObj = OSD_GetFocusObject(pObj);
	Result = OSD_ObjProc(pObj,(MSG_TYPE_EVNT<<16) | EVN_PRE_OPEN, (UINT32)pFoucsObj,param);    
	if(Result != PROC_PASS)
		return Result;
    add_object_record(pObj);

	nCmdDraw = 	C_DRAW_SIGN_EVN_FLG | C_UPDATE_ALL | C_DRAW_TYPE_HIGHLIGHT;
	Result = OSD_TrackObject((POBJECT_HEAD)pObj,nCmdDraw);
	pFoucsObj = OSD_GetFocusObject(pObj);
	Result = OSD_ObjProc(pObj,(MSG_TYPE_EVNT<<16) |EVN_POST_OPEN,(UINT32)pFoucsObj,param);  

	if(pObj->pRoot == NULL)
		OSD_UpdateVscr(&g_vscr[vscr_idx - 1]); 

	return PROC_PASS;
}

PRESULT OSD_ObjClose(POBJECT_HEAD pObj, UINT32 param)
{
	PRESULT Result;
	OBJECT_HEAD *pFoucsObj;
	UINT32 vscr_idx,evtpara;

	vscr_idx = osal_task_get_current_id();
	if((vscr_idx == OSAL_INVALID_ID) || (vscr_idx > OSD_DRAW_TASK_MAX))
		ASSERT(0);
	if(pObj->pRoot != NULL)
		return PROC_LOOP;

	evtpara = param;
	pFoucsObj = OSD_GetFocusObject(pObj);
	Result = OSD_ObjProc(pObj,(MSG_TYPE_EVNT<<16) |EVN_PRE_CLOSE,(UINT32)pFoucsObj,(UINT32)&evtpara);    
	if(Result != PROC_PASS)
		return Result;

	if(param & evtpara & C_CLOSE_CLRBACK_FLG)
		OSD_ClearObject(pObj,0);

	Result = OSD_ObjProc(pObj,(MSG_TYPE_EVNT<<16) |EVN_POST_CLOSE,(UINT32)pFoucsObj,(UINT32)param);   

	if(g_vscr[vscr_idx - 1].lpbScr != NULL)
		OSD_UpdateVscr(&g_vscr[vscr_idx - 1]);
	g_vscr[vscr_idx - 1].lpbScr = NULL;

    del_object_record(pObj);

	return PROC_LEAVE;
}


PRESULT OSD_ObjCommonProc(POBJECT_HEAD pObj, UINT32 hkey, UINT32 Param,
						  UINT32* pvkey,VACTION* pvact,BOOL* bContinue)
{
	PRESULT Result;
	VACTION Action = VACT_PASS;
	UINT32	vkey;
	UINT32	i = 0;
	*bContinue = FALSE;

	/*If no keymap function,it means the object doesn't process 
	key message */

	if(pObj->pfnKeyMap == NULL)
		return OSD_SIGNAL(pObj,EVN_UNKNOWNKEY_GOT,hkey,Param);

	do
	{
		i = g_osd_rsc_info.ap_hk_to_vk(i, hkey, &vkey);   // hk_to_vkey() provided by framework 
		if(vkey!=V_KEY_NULL)            //vkey=V_KEY_NULL -> Search keymap array end
			Action = pObj->pfnKeyMap(pObj,vkey);
	}while(Action == VACT_PASS && vkey!=V_KEY_NULL); 
	
	*pvkey = vkey;
	*pvact  = Action;
	
	/* If it's a invalid key for this object, 
	sign an unknown key event */
	if(vkey==V_KEY_NULL)    // Action ==VACT_PASS 
		return OSD_SIGNAL(pObj,EVN_UNKNOWNKEY_GOT,hkey,Param);
	
	if(Action == VACT_PASS)
		return PROC_PASS;//return OSD_SIGNAL(pObj,EVN_UNKNOWN_ACTION,(Action<<16) | vkey,Param);
	/* If it's a valid key for this object, 
	sign a key got event. */
	Result = OSD_SIGNAL(pObj, EVN_KEY_GOT, (Action<<16) | vkey, Param);

	/*If callback return not PASS but LOOP or LEAVE, 
	don't do any further processing */
	if(Result == PROC_LOOP || Result ==PROC_LEAVE)
		return Result;

	*bContinue = TRUE;            	        

	return PROC_PASS;
}


PRESULT OSD_ObjProc(POBJECT_HEAD pObj, UINT32 msg_type,UINT32 msg,UINT32 param1)
{
	PRESULT Result= PROC_PASS;
	UINT16	osd_msg_type, user_define_type;
	UINT32 vscr_idx;
	
	vscr_idx = osal_task_get_current_id();
	if((vscr_idx == OSAL_INVALID_ID) || (vscr_idx > OSD_DRAW_TASK_MAX))
		ASSERT(0);
	osd_msg_type = msg_type>>16;
	user_define_type = (UINT16)msg_type;
	if((MSG_TYPE_KEY == osd_msg_type)  || (MSG_TYPE_EVNT == osd_msg_type))
	{
		if(MSG_TYPE_EVNT == osd_msg_type)
			osd_msg_type = user_define_type;
			
		switch(pObj->bType)
		{
		 case OT_TEXTFIELD:
		 	Result = OSD_TextFieldProc(pObj,osd_msg_type,msg,param1);
		 	break;
		 case OT_BITMAP:
		 	Result = OSD_BitmapProc(pObj,osd_msg_type,msg,param1);
		 	break;
		case OT_EDITFIELD:
			Result = OSD_EditFieldProc(pObj,osd_msg_type,msg,param1);
		 	break;
		 case OT_MULTISEL:
		 	Result = OSD_MultiselProc(pObj,osd_msg_type,msg,param1);
		 	break;
		 case OT_PROGRESSBAR:
		 	Result = OSD_ProgressBarProc(pObj,osd_msg_type,msg,param1);
		 	break;
		 case OT_SCROLLBAR:
		 	Result = OSD_ScrollBarProc(pObj,osd_msg_type,msg,param1);
		 	break;
		 case OT_MULTITEXT:
		 	Result = OSD_MultiTextProc(pObj,osd_msg_type,msg,param1);
		 	break;
		 case OT_LIST:
		 	Result = OSD_ListProc(pObj,osd_msg_type,msg,param1);
		 	break;
		 case OT_MATRIXBOX:
		 	Result = OSD_MatrixboxProc(pObj,osd_msg_type,msg,param1);
		 	break;
		 case OT_OBJLIST:
		 	Result = OSD_ObjectListProc(pObj,osd_msg_type,msg,param1);
		 	break;
		 case OT_CONTAINER:
		 	Result = OSD_ContainerProc(pObj,osd_msg_type,msg,param1);
		 	break;
		 case OT_ANIMATION:
		 	Result = OSD_AnimationProc(pObj,osd_msg_type,msg,param1);
		 	break;
		 default:
		 	;			 			
		}
	}
	else if(osd_msg_type == MSG_TYPE_MSG)	/* Evnt will not pass to it's sub object*/
	{
		Result = OSD_SIGNAL(pObj,EVN_MSG_GOT,user_define_type,msg);
		if(Result == PROC_LEAVE)
			Result = OSD_ObjClose(pObj,C_CLOSE_CLRBACK_FLG);
	}
	
	/*Check wether any unsubmited virtual screen,
	    if so ,submit the virtual screen to osd buffer*/
	if(pObj->pRoot == NULL)
		OSD_UpdateVscr(&g_vscr[vscr_idx - 1]);

	return Result;
}

void OSD_RegionInit(struct OSD_RegionInfo *p_region_info,struct OSD_RscInfo *p_rsc_info)
{
	UINT8 *p_pallette;
	UINT32 trans_color;
	struct OSDPara	OsdOpenPara;
    struct OSDRect rect;
    
	MEMSET(&g_ge_surface_info,0x0,sizeof(struct OSD_SurfaceInfo));
	MEMCPY(&(g_osd_region_info.tOpenPara),&(p_region_info->tOpenPara),sizeof(struct OSDPara));/*Copy Configure parameter*/
	MEMCPY(&(g_osd_region_info.osdrect),&(p_region_info->osdrect),sizeof(struct OSDRect));/*Copy Configure parameter*/
	MEMCPY(&OsdOpenPara,&(p_region_info->tOpenPara),sizeof(struct OSDPara));/*Copy Configure parameter*/
    g_osd_region_info.uIsUseVSCR = p_region_info->uIsUseVSCR;
	if(!OSD_ColorModeIsCLUT(OsdOpenPara.eMode))
	{
		if(p_region_info->tOpenPara.eMode == OSD_HD_ARGB8888)
			OsdOpenPara.eMode = OSD_HD_AYCbCr8888;
	}	

	OSD_SetDeviceHandle((HANDLE)p_region_info->osddev_handle);
	OSDDrv_Open((HANDLE)p_region_info->osddev_handle, &OsdOpenPara);
	trans_color = OSD_GetTransColor(OsdOpenPara.eMode, TRUE);
	OSDDrv_IoCtl((HANDLE)p_region_info->osddev_handle, OSD_IO_SET_TRANS_COLOR, trans_color);
	OSDDrv_CreateRegion((HANDLE)p_region_info->osddev_handle, 0, &(p_region_info->osdrect), NULL);   
	OSD_SetCurRegion(0);

	OSD_TaskBuffer_Free(osal_task_get_current_id(),NULL);
	OSD_GolobalVscr_Init();
#ifdef GE_DRAW_OSD_LIB 
    if(p_region_info->uIsUseVSCR == 1)
#endif
    {
        OSD_TaskBuffer_Init(osal_task_get_current_id(), (UINT8 *)__MM_OSD_VSRC_MEM_ADDR);
    }
    
	p_region_info->osdrect.uLeft = p_region_info->osdrect.uTop = 0;

	g_osd_rsc_info.osd_get_font_lib = p_rsc_info->osd_get_font_lib;
	g_osd_rsc_info.osd_get_lang_env = p_rsc_info->osd_get_lang_env;
	g_osd_rsc_info.osd_get_obj_info = p_rsc_info->osd_get_obj_info;
	g_osd_rsc_info.osd_get_rsc_data =p_rsc_info->osd_get_rsc_data ;
	g_osd_rsc_info.osd_get_thai_font_data =p_rsc_info->osd_get_thai_font_data;
	g_osd_rsc_info.osd_get_str_lib_id = p_rsc_info->osd_get_str_lib_id;
	g_osd_rsc_info.osd_get_win_style = p_rsc_info->osd_get_win_style ;
	g_osd_rsc_info.osd_rel_rsc_data = p_rsc_info->osd_rel_rsc_data;
#ifdef BIDIRECTIONAL_OSD_STYLE
	g_osd_rsc_info.osd_get_mirror_flag = p_rsc_info->osd_get_mirror_flag;
#endif
	g_osd_rsc_info.ap_hk_to_vk = p_rsc_info->ap_hk_to_vk;/*Attach Rsc functions*/
	p_pallette = OSD_GetRscPallette(0x4080 | 0);
	OSD_SetPallette(p_pallette,COLOR_N);
    rect = p_region_info->osdrect;
    rect.uTop = rect.uLeft = 0;
    //20131118. For 32bit UI, the region area will not be slight transparent.
    if(OSD_ColorModeIs32bit(OsdOpenPara.eMode)) 
    {
       trans_color = OSD_GetHDAlphaColor(trans_color);
    }
#ifdef BIDIRECTIONAL_OSD_STYLE
	if (g_osd_rsc_info.osd_get_mirror_flag() == TRUE)
		OSDDrv_RegionFill32Inverse((HANDLE)p_region_info->osddev_handle,0,&(p_region_info->osdrect),trans_color);
	else
#endif
	OSDDrv_RegionFill32((HANDLE)p_region_info->osddev_handle,0,&(p_region_info->osdrect),trans_color);
	OSDDrv_ShowOnOff((HANDLE)p_region_info->osddev_handle,OSDDRV_ON);
#ifdef SUPPORT_DRAW_EFFECT    
    OSD_DrawMode_init(&(g_osd_region_info.osdrect),OSD_HD_ARGB1555);
#endif

#ifdef GE_DRAW_OSD_LIB 
    lib_ge_draw_open(dev_get_by_type(NULL,HLD_DEV_TYPE_GE));   
    OSD_GeDraw_Init((HANDLE)p_region_info->osddev_handle,p_region_info->uIsUseVSCR,0);
#endif
}
#ifdef _INVW_JUICE
void OSD_RegionInit_restore(struct OSD_RegionInfo *p_region_info,struct OSD_RscInfo *p_rsc_info)
{
	UINT8 *p_pallette;
	UINT32 trans_color;
	struct OSDPara	OsdOpenPara;
    struct OSDRect rect;
    
	OSDDrv_ShowOnOff((HANDLE)p_region_info->osddev_handle,OSDDRV_OFF);
	OSDDrv_Close((HANDLE)p_region_info->osddev_handle);
		
	MEMSET(&g_ge_surface_info,0x0,sizeof(struct OSD_SurfaceInfo));
	MEMCPY(&(g_osd_region_info.tOpenPara),&(p_region_info->tOpenPara),sizeof(struct OSDPara));/*Copy Configure parameter*/
	MEMCPY(&(g_osd_region_info.osdrect),&(p_region_info->osdrect),sizeof(struct OSDRect));/*Copy Configure parameter*/
	MEMCPY(&OsdOpenPara,&(p_region_info->tOpenPara),sizeof(struct OSDPara));/*Copy Configure parameter*/
    g_osd_region_info.uIsUseVSCR = p_region_info->uIsUseVSCR;
	if(!OSD_ColorModeIsCLUT(OsdOpenPara.eMode))
	{
		if(p_region_info->tOpenPara.eMode == OSD_HD_ARGB8888)
			OsdOpenPara.eMode = OSD_HD_AYCbCr8888;
	}	

	OSD_SetDeviceHandle((HANDLE)p_region_info->osddev_handle);
	OSDDrv_Open((HANDLE)p_region_info->osddev_handle, &OsdOpenPara);
	trans_color = OSD_GetTransColor(OsdOpenPara.eMode, TRUE);
	OSDDrv_IoCtl((HANDLE)p_region_info->osddev_handle, OSD_IO_SET_TRANS_COLOR, trans_color);
	OSDDrv_CreateRegion((HANDLE)p_region_info->osddev_handle, 0, &(p_region_info->osdrect), NULL);   
	OSD_SetCurRegion(0);

	OSD_TaskBuffer_Free(osal_task_get_current_id(),NULL);
	OSD_GolobalVscr_Init();
#ifdef GE_DRAW_OSD_LIB 
    if(p_region_info->uIsUseVSCR == 1)
#endif
    {
        OSD_TaskBuffer_Init(osal_task_get_current_id(), (UINT8 *)__MM_OSD_VSRC_MEM_ADDR);
    }
    
	OSDDrv_ShowOnOff((HANDLE)p_region_info->osddev_handle,OSDDRV_ON);
	
	p_region_info->osdrect.uLeft = p_region_info->osdrect.uTop = 0;

#if 0
	g_osd_rsc_info.osd_get_font_lib = p_rsc_info->osd_get_font_lib;
	g_osd_rsc_info.osd_get_lang_env = p_rsc_info->osd_get_lang_env;
	g_osd_rsc_info.osd_get_obj_info = p_rsc_info->osd_get_obj_info;
	g_osd_rsc_info.osd_get_rsc_data =p_rsc_info->osd_get_rsc_data ;
	g_osd_rsc_info.osd_get_thai_font_data =p_rsc_info->osd_get_thai_font_data;
	g_osd_rsc_info.osd_get_str_lib_id = p_rsc_info->osd_get_str_lib_id;
	g_osd_rsc_info.osd_get_win_style = p_rsc_info->osd_get_win_style ;
	g_osd_rsc_info.osd_rel_rsc_data = p_rsc_info->osd_rel_rsc_data;
#ifdef BIDIRECTIONAL_OSD_STYLE
	g_osd_rsc_info.osd_get_mirror_flag = p_rsc_info->osd_get_mirror_flag;
#endif
	g_osd_rsc_info.ap_hk_to_vk = p_rsc_info->ap_hk_to_vk;/*Attach Rsc functions*/
#endif


#if 0
	p_pallette = OSD_GetRscPallette(0x4080 | 0);
	OSD_SetPallette(p_pallette,COLOR_N);


	
    rect = p_region_info->osdrect;
    rect.uTop = rect.uLeft = 0;
#endif

#if 0
	
#ifdef BIDIRECTIONAL_OSD_STYLE
	if (g_osd_rsc_info.osd_get_mirror_flag() == TRUE)
		OSDDrv_RegionFill32Inverse((HANDLE)p_region_info->osddev_handle,0,&(p_region_info->osdrect),trans_color);
	else
#endif

#endif

#if 0
	 	osal_delay_ms(500);
	OSDDrv_RegionFill32((HANDLE)p_region_info->osddev_handle,0,&(p_region_info->osdrect),trans_color);
	OSDDrv_ShowOnOff((HANDLE)p_region_info->osddev_handle,OSDDRV_ON);
#endif

#if 0
	
#ifdef SUPPORT_DRAW_EFFECT    
    OSD_DrawMode_init(&(g_osd_region_info.osdrect),OSD_HD_ARGB1555);
#endif

#ifdef GE_DRAW_OSD_LIB 
    lib_ge_draw_open(dev_get_by_type(NULL,HLD_DEV_TYPE_GE));   
    OSD_GeDraw_Init((HANDLE)p_region_info->osddev_handle,p_region_info->uIsUseVSCR,0);
#endif
#endif
}

#endif

#if 1
void OSD_SmallRegionInit(struct OSD_RegionInfo *p_region_info,struct OSD_RscInfo *p_rsc_info)
{
	UINT8 *p_pallette;
	UINT32 trans_color;
	struct OSDPara	OsdOpenPara;
    struct OSDRect rect;
    
	//MEMSET(&g_ge_surface_info,0x0,sizeof(struct OSD_SurfaceInfo));
	///MEMCPY(&(g_osd_region_info.tOpenPara),&(p_region_info->tOpenPara),sizeof(struct OSDPara));/*Copy Configure parameter*/
	//MEMCPY(&(g_osd_region_info.osdrect),&(p_region_info->osdrect),sizeof(struct OSDRect));/*Copy Configure parameter*/
	MEMCPY(&OsdOpenPara,&(p_region_info->tOpenPara),sizeof(struct OSDPara));/*Copy Configure parameter*/

	if(!OSD_ColorModeIsCLUT(OsdOpenPara.eMode))
	{
		if(OsdOpenPara.eMode == OSD_HD_ARGB8888)
			OsdOpenPara.eMode = OSD_HD_AYCbCr8888;
	}

	//OSD_SetDeviceHandle((HANDLE)p_region_info->osddev_handle);
	OSDDrv_Open((HANDLE)p_region_info->osddev_handle, &OsdOpenPara);
	trans_color = OSD_GetTransColor(OsdOpenPara.eMode, TRUE);
	OSDDrv_IoCtl((HANDLE)p_region_info->osddev_handle, OSD_IO_SET_TRANS_COLOR, trans_color);
	OSDDrv_CreateRegion((HANDLE)p_region_info->osddev_handle, 0, &(p_region_info->osdrect), NULL);   
	//OSD_SetCurRegion(0);

	//OSD_TaskBuffer_Free(osal_task_get_current_id(),NULL);
	//OSD_GolobalVscr_Init();
	//OSD_TaskBuffer_Init(osal_task_get_current_id(),__MM_OSD_VSRC_MEM_ADDR);

	p_region_info->osdrect.uLeft = p_region_info->osdrect.uTop = 0;

	//g_osd_rsc_info.osd_get_font_lib = p_rsc_info->osd_get_font_lib;
	//g_osd_rsc_info.osd_get_lang_env = p_rsc_info->osd_get_lang_env;
	//g_osd_rsc_info.osd_get_obj_info = p_rsc_info->osd_get_obj_info;
	//g_osd_rsc_info.osd_get_rsc_data =p_rsc_info->osd_get_rsc_data ;
	//g_osd_rsc_info.osd_get_thai_font_data =p_rsc_info->osd_get_thai_font_data;
	//g_osd_rsc_info.osd_get_str_lib_id = p_rsc_info->osd_get_str_lib_id;
	//g_osd_rsc_info.osd_get_win_style = p_rsc_info->osd_get_win_style ;
	//g_osd_rsc_info.osd_rel_rsc_data = p_rsc_info->osd_rel_rsc_data;
	//g_osd_rsc_info.ap_hk_to_vk = p_rsc_info->ap_hk_to_vk;/*Attach Rsc functions*/
	p_pallette = OSD_GetRscPallette(0x4080 | 0);
	//OSD_SetPallette(p_pallette,COLOR_N);
	OSDDrv_SetPallette(p_region_info->osddev_handle,p_pallette,COLOR_N,OSDDRV_YCBCR);
    rect = p_region_info->osdrect;
    rect.uTop = rect.uLeft = 0;
	OSDDrv_RegionFill((HANDLE)p_region_info->osddev_handle,0,&(p_region_info->osdrect),trans_color|0xF0);
	OSDDrv_ShowOnOff((HANDLE)p_region_info->osddev_handle,OSDDRV_ON);
}
#endif

BOOL OSD_SwitchRegion(VSCR* pVscr,UINT32 new_color_mode)
{
	UINT8 *p_pallette;
	UINT32 old_color_mode;
	UINT32 trans_color;
	struct OSD_RegionInfo region_info;
	struct OSD_RegionInfo *p_region_info;
	OSD_Resize_Param  osd_rsz_par;  
    UINT32 osd_on_off = 0xFFFF;
    struct OSDRect rect;
	old_color_mode = g_osd_region_info.tOpenPara.eMode;
	if(old_color_mode == new_color_mode || new_color_mode == 0 || old_color_mode == 0)
		return FALSE;

	pVscr->bColorMode = new_color_mode;
	g_osd_region_info.tOpenPara.eMode = new_color_mode;

	p_region_info = &region_info;
	MEMCPY(p_region_info,&g_osd_region_info,sizeof(g_osd_region_info));

	if(!OSD_ColorModeIsCLUT(new_color_mode))
	{
		if(new_color_mode == OSD_HD_ARGB8888 || new_color_mode == OSD_HD_AYCbCr8888)
			p_region_info->tOpenPara.eMode = OSD_HD_AYCbCr8888;
		else if(new_color_mode == OSD_HD_ARGB1555)
			p_region_info->tOpenPara.eMode = OSD_HD_ARGB1555;
		else if(new_color_mode == OSD_HD_ARGB4444)
			p_region_info->tOpenPara.eMode = OSD_HD_ARGB4444;
	}

    OSDDrv_IoCtl((HANDLE)p_region_info->osddev_handle,OSD_IO_GET_ON_OFF,(UINT32)(&osd_on_off));
    if(osd_on_off != OSDDRV_OFF)
    {
	    OSDDrv_ShowOnOff((HANDLE)p_region_info->osddev_handle,OSDDRV_OFF);
        osal_task_sleep(30);
    }

    OSDDrv_IoCtl((HANDLE)p_region_info->osddev_handle,OSD_IO_GET_RESIZE_PARAMATER,(UINT32)(&osd_rsz_par));
	trans_color = OSD_GetTransColor(p_region_info->tOpenPara.eMode, TRUE);
	OSDDrv_IoCtl((HANDLE)p_region_info->osddev_handle, OSD_IO_SET_TRANS_COLOR, trans_color);
    OSDDrv_IoCtl((HANDLE)p_region_info->osddev_handle,OSD_IO_SET_AUTO_CLEAR_REGION,FALSE);
    OSDDrv_DeleteRegion((HANDLE)p_region_info->osddev_handle, p_region_info->region_id);
	OSDDrv_CreateRegion((HANDLE)p_region_info->osddev_handle, p_region_info->region_id, &(p_region_info->osdrect), &p_region_info->tOpenPara); 
    OSDDrv_IoCtl((HANDLE)p_region_info->osddev_handle,OSD_IO_SET_RESIZE_PARAMATER,(UINT32)(&osd_rsz_par));
    OSDDrv_IoCtl((HANDLE)p_region_info->osddev_handle,OSD_IO_SET_AUTO_CLEAR_REGION,TRUE);    
	OSD_SetCurRegion(0);	

	//trans_color = OSD_GetTransColor(new_color_mode, FALSE);
	if(OSD_ColorModeIsCLUT(new_color_mode))
	{
		p_pallette = OSD_GetRscPallette(0x4080 | 0);
		OSD_SetPallette(p_pallette,COLOR_N);
	}
	OSD_InitVscrColor(pVscr, trans_color);
	rect.uLeft = 0;
	rect.uTop = 0;
	rect.uWidth = p_region_info->osdrect.uWidth;
	rect.uHeight = p_region_info->osdrect.uHeight;
#ifdef BIDIRECTIONAL_OSD_STYLE
	if (g_osd_rsc_info.osd_get_mirror_flag() == TRUE)
		OSDDrv_RegionFill32Inverse((HANDLE)p_region_info->osddev_handle,0,&rect,trans_color);
	else
#endif
	OSDDrv_RegionFill32((HANDLE)p_region_info->osddev_handle,0,&rect,trans_color);
	OSDDrv_Scale((HANDLE)p_region_info->osddev_handle, 0xff, 0);
    if(osd_on_off != OSDDRV_OFF)
    {
        OSDDrv_ShowOnOff((HANDLE)p_region_info->osddev_handle,OSDDRV_ON);
    }
#ifdef GE_DRAW_OSD_LIB
    OSD_GeDraw_Init((HANDLE)p_region_info->osddev_handle,g_osd_region_info.uIsUseVSCR,0);
#endif    
	return TRUE;
}

void OSD_SurfaceInit(struct OSD_SurfaceInfo *p_surface_info,struct OSD_RscInfo *p_rsc_info)
{
	UINT8 *p_pallette;
	ge_region_t region_para;
	ge_surface_desc_t  surf_para;

	
	MEMSET(&g_osd_region_info,0x0,sizeof(struct OSD_RegionInfo));
	MEMCPY(&g_ge_surface_info,p_surface_info,sizeof(struct OSD_SurfaceInfo));
	OSDDrv_IoCtl((HANDLE)g_ge_surface_info.ge_dev, GE_IO_SET_TRANS_COLOR, OSD_TRANSPARENT_COLOR);

	surf_para.width = g_ge_surface_info.ge_region_para.rect.width;
	surf_para.height = g_ge_surface_info.ge_region_para.rect.height;
	surf_para.pitch = 720;//surf_para.width >> 0; 
	surf_para.endian = GE_PIXEL_LITTLE_ENDIAN;
	surf_para.alpha_range = GE_LITTLE_ALPHA;
	g_ge_surface_info.ge_dissf = ge_create_surface(g_ge_surface_info.ge_dev, &surf_para, 0, GMA_HW_SURFACE_1);	
	g_ge_surface_info.ge_virsf = ge_create_surface(g_ge_surface_info.ge_dev, &surf_para, 0, GMA_MEM_SURFACE);	

	g_ge_surface_info.dissf_region_id = 0;
	g_ge_surface_info.virsf_region_id = 0;
	region_para.rect.left = g_ge_surface_info.ge_region_para.rect.left;
	region_para.rect.top = g_ge_surface_info.ge_region_para.rect.top;
	region_para.rect.width = surf_para.width;
	region_para.rect.height = surf_para.height;
	region_para.pitch = surf_para.width >> 0; 
	region_para.glob_alpha_en = 0;
	region_para.glob_alpha = 0x7f;
	region_para.pallet_seg = 0;
	region_para.pixel_fmt = GE_PF_CLUT8;
	ge_create_region(g_ge_surface_info.ge_dev, g_ge_surface_info.ge_dissf, 0, &region_para.rect, &region_para);
	ge_create_region(g_ge_surface_info.ge_dev, g_ge_surface_info.ge_virsf, 0, &region_para.rect, &region_para);

	OSD_GolobalVscr_Init();
	OSD_TaskBuffer_Init(osal_task_get_current_id(),NULL);/*Library buffer init*/
	
	g_osd_rsc_info.osd_get_font_lib = p_rsc_info->osd_get_font_lib;
	g_osd_rsc_info.osd_get_lang_env = p_rsc_info->osd_get_lang_env;
	g_osd_rsc_info.osd_get_obj_info = p_rsc_info->osd_get_obj_info;
	g_osd_rsc_info.osd_get_rsc_data =p_rsc_info->osd_get_rsc_data ;
	g_osd_rsc_info.osd_get_thai_font_data =p_rsc_info->osd_get_thai_font_data;
	g_osd_rsc_info.osd_get_str_lib_id = p_rsc_info->osd_get_str_lib_id;
	g_osd_rsc_info.osd_get_win_style = p_rsc_info->osd_get_win_style ;
	g_osd_rsc_info.osd_rel_rsc_data = p_rsc_info->osd_rel_rsc_data;
#ifdef BIDIRECTIONAL_OSD_STYLE
	g_osd_rsc_info.osd_get_mirror_flag = p_rsc_info->osd_get_mirror_flag;
#endif
	g_osd_rsc_info.ap_hk_to_vk = p_rsc_info->ap_hk_to_vk;/*Attach Rsc functions*/
	
	p_pallette = OSD_GetRscPallette(0x4080 | 0);
	OSD_SetPallette(p_pallette,COLOR_N);
	ge_fill_rect(g_ge_surface_info.ge_dev,g_ge_surface_info.ge_dissf, &region_para.rect,OSD_TRANSPARENT_COLOR);
	ge_show_onoff(g_ge_surface_info.ge_dev,g_ge_surface_info.ge_dissf,1);/*Ge library clear operation*/
}

OSD_DRAW_DEV_MODE OSD_GetDrawMode()
{
	OSD_DRAW_DEV_MODE mode;

	mode = GE_DRAW_MODE;
	if(g_osd_region_info.osddev_handle != (UINT32)NULL)/*OSD_DRAW valid*/
		mode = OSD_DRAW_MODE;

	return mode;
}

void OSD_SetDrawMode(OSD_DRAW_DEV_MODE mode_chg)
{
	if(0)
	{
		//TODO:change between GE & OSD mode
	}
	return;
}

void OSD_SetWholeObjAttr(POBJECT_HEAD	pObj, UINT8 bAttr)
{
	POBJECT_HEAD	pNext;

	pObj->bAttr = bAttr;
	
	if(OT_CONTAINER == pObj->bType)
	{
		pNext = ((CONTAINER*)pObj)->pNextInCntn;
		while(NULL != pNext)
		{
			pNext->bAttr = bAttr;
			if(OT_CONTAINER == pNext->bType)
				OSD_SetWholeObjAttr(pNext, bAttr);
				
			pNext = pNext->pNext;
		}
	}
}
enum OSDColorMode OSD_GetCurColorMode()
{
	return g_osd_region_info.tOpenPara.eMode;
}

void OSD_SetPaletteBoardEx(UINT32 wPalIdx, UINT32 nColor)
{
	static struct osd_device * osd_dev =NULL;
	osd_dev = (struct osd_device *)dev_get_by_id(HLD_DEV_TYPE_OSD, 1);
	
//	OSDDrv_ModifyPallette((HANDLE)osd_dev,UINT8 uIndex,UINT8 uY,UINT8 uCb,UINT8 uCr,UINT8 uK)
}

void OSD_SetPaletteBoard(UINT32 wPalIdx, UINT32 nColor)
{
    OSD_SetPaletteBoardEx(wPalIdx, nColor);
}

#ifdef TXT_RUNNER_SUPPORT
struct RUNTXTMAP osd_runer_txtObj1;
struct RUNTXTMAP osd_runer_orginal_txtObj1;
struct RUNTXTMAP osd_runer_txtObj2;
struct RUNTXTMAP osd_runer_orginal_txtObj2;
struct RUNTXTMAP osd_runer_txtObj3;
struct RUNTXTMAP osd_runer_orginal_txtObj3;
struct RUNTXTMAP osd_running_Obj;

UINT16 uoffset_xvalue=0;
UINT16 obj_run_mode=0;
UINT16 obj_run_total_strlen=0;

UINT8 runner_obj_change_value=0;
UINT8 total_runner_obj_value=0;
struct OSDRect runner_size;

struct OSDRect runner_size1;
struct OSDRect runner_size2;
struct OSDRect runner_size3;

void Set_OSD_TXT_Runner_Obj(struct RUNTXTMAP pObj1,struct RUNTXTMAP pObj2,struct RUNTXTMAP pObj3)
{
	if(pObj1.run_head !=NULL)
		{
			total_runner_obj_value=1;
			MEMCPY(&osd_runer_txtObj1,&pObj1,sizeof(struct RUNTXTMAP));
		}
	
	if(pObj2.run_head !=NULL)
		{
			total_runner_obj_value=2;
			MEMCPY(&osd_runer_txtObj2,&pObj2,sizeof(struct RUNTXTMAP ));
		}
	
	if(pObj3.run_head !=NULL)
		{
			total_runner_obj_value=3;	
			MEMCPY(&osd_runer_txtObj3,&pObj3,sizeof(struct RUNTXTMAP));
		}

}

void Close_OSD_TXT_Runner_Obj()
{
	 uoffset_xvalue=0;
	 obj_run_mode=0;
	 obj_run_total_strlen=0;

	 runner_obj_change_value=0;
	 total_runner_obj_value=0;
	MEMSET(&osd_runer_txtObj1,0,sizeof(struct RUNTXTMAP));
	MEMSET(&osd_runer_txtObj2,0,sizeof(struct RUNTXTMAP));
	MEMSET(&osd_runer_txtObj3,0,sizeof(struct RUNTXTMAP));
}

 POBJECT_HEAD Get_OSD_TXT_Runner_Obj(UINT8 index)
{
	if(index==0)
		return osd_runer_txtObj1.run_head;
	else if(index==1)
		return osd_runer_txtObj2.run_head;
	else if(index==2)
		return osd_runer_txtObj3.run_head;
	else
		return osd_runer_txtObj1.run_head;
}

 void Get_OSD_TXT_Runner_TextField_width(UINT8 index,struct OSDRect *pRect1)
{

	if(index==0)
		MEMCPY(pRect1,&(osd_runer_txtObj1.run_head->frame),sizeof(struct OSDRect));
	else if(index==1)
		MEMCPY(pRect1,&(osd_runer_txtObj2.run_head->frame),sizeof(struct OSDRect));
	else if(index==2)
		MEMCPY(pRect1,&(osd_runer_txtObj3.run_head->frame),sizeof(struct OSDRect));
	else
		MEMCPY(pRect1,&(osd_runer_txtObj1.run_head->frame),sizeof(struct OSDRect));
}
 
void Get_OSD_TXT_Runner_Map(UINT8 index,struct RUNTXTMAP *pObj1)
{
	if(index==0)
		MEMCPY(pObj1,&osd_runer_txtObj1,sizeof(struct RUNTXTMAP));
	else if(index==1)
		MEMCPY(pObj1,&osd_runer_txtObj2,sizeof(struct RUNTXTMAP));
	else if(index==2)
		MEMCPY(pObj1,&osd_runer_txtObj3,sizeof(struct RUNTXTMAP));
	else
		MEMCPY(pObj1,&osd_runer_txtObj1,sizeof(struct RUNTXTMAP));
}

void Set_OSD_TXT_Runner_Offset_Value(UINT8 index,UINT16 value)
{
	if(index==0)
		osd_runer_txtObj1.offset_value=value;
	else if(index==1)
		osd_runer_txtObj2.offset_value=value;
	else if(index==2)
		osd_runer_txtObj3.offset_value=value;
	else
		osd_runer_txtObj1.offset_value=value;}

UINT8 OSD_Draw_TXT_Runner(struct RUNTXTMAP pObj1,struct RUNTXTMAP pObj2,struct RUNTXTMAP pObj3)
{
	POBJECT_HEAD oh;
	OBJECT_HEAD *pFoucsObj;
	PTEXT_FIELD *pTxt;
	UINT8 bFocusID;
	UINT32 drawType;
	UINT32 nCmdDraw;
	UINT8 result=FALSE;
	//Set_OSD_TXT_Runner_Obj(pObj);
	if(pObj1.run_head==NULL)
		result=FALSE;
	else
		result=TRUE;

	if(result==TRUE)
		{
			result=FALSE;
			Set_OSD_TXT_Runner_Obj(pObj1,pObj2,pObj3);
			if(pObj1.run_head !=NULL)
				{
					MEMCPY(&runner_size1,&(osd_runer_txtObj1.run_head->frame),sizeof(struct OSDRect));
					if((osd_runer_txtObj1.total_strlen) > (runner_size1.uWidth))
						return TRUE;
				}
			if(pObj2.run_head !=NULL)
				{
					MEMCPY(&runner_size2,&(osd_runer_txtObj2.run_head->frame),sizeof(struct OSDRect));
					if((osd_runer_txtObj2.total_strlen) > (runner_size2.uWidth))
						return TRUE;
				}
			if(pObj3.run_head !=NULL)
				{
					MEMCPY(&runner_size3,&(osd_runer_txtObj3.run_head->frame),sizeof(struct OSDRect));
					if((osd_runer_txtObj3.total_strlen) > (runner_size3.uWidth))
						return TRUE;
				}			
		}
	return result;
			
}

UINT8 OSD_Draw_Con_TXT_Runner(struct RUNTXTMAP pObj)
{
	POBJECT_HEAD oh;
	OBJECT_HEAD *pFoucsObj;
	PTEXT_FIELD runer_string;
	UINT8 bFocusID;
	UINT32 drawType;
	UINT32 nCmdDraw;
	UINT8 result=FALSE;
	struct RUNTXTMAP temp_pObj;
	struct RUNTXTMAP temp_pObj2;
	struct RUNTXTMAP temp_pObj3;
	UINT16 	uMaxHeight,uMaxWidth;	
	//Set_OSD_TXT_Runner_Obj(pObj);
	MEMSET(&temp_pObj,0,sizeof(struct RUNTXTMAP));
	MEMSET(&temp_pObj2,0,sizeof(struct RUNTXTMAP));
	MEMSET(&temp_pObj3,0,sizeof(struct RUNTXTMAP));
	
	MEMCPY(&temp_pObj,&pObj,sizeof(struct RUNTXTMAP));
#if 1
	pFoucsObj=OSD_GetFocusObject((POBJECT_HEAD)temp_pObj.run_head);
	drawType=C_DRAW_TYPE_NORMAL;
	nCmdDraw=C_UPDATE_ALL;
	OSD_SetDrawType(nCmdDraw,drawType);

	while(pFoucsObj->bType!=OT_TEXTFIELD)
		{
			bFocusID = OSD_GetFocusID(pFoucsObj);
			pFoucsObj   = OSD_GetObject(pFoucsObj, bFocusID);    		
			if(pFoucsObj==NULL)
				break;
		}
#endif		
	if(pFoucsObj==NULL)
		result=FALSE;
	else
		result=TRUE;

	if(result==TRUE)
		{
			temp_pObj.run_head=(POBJECT_HEAD)pFoucsObj;
			runer_string=(PTEXT_FIELD)temp_pObj.run_head;
			temp_pObj.total_strlen=OSD_MultiFontLibStrMaxHW(runer_string->pString, runer_string->head.bFont, &uMaxHeight, &uMaxWidth,0);
			Set_OSD_TXT_Runner_Obj(temp_pObj,temp_pObj2,temp_pObj3);
			MEMCPY(&runner_size1,&(osd_runer_txtObj1.run_head->frame),sizeof(struct OSDRect));
			if((temp_pObj.total_strlen) < (runner_size1.uWidth))
				result=FALSE;
		}
	return result;
		
}
void Start_TXT_Runner()
{
	UINT8  bStyleIdx;
	UINT8 bFocusID;
	UINT32 drawType;
	UINT32 nCmdDraw;
	UINT32 vscr_idx;
	struct OSDRect *objframe;
	UINT32 mem_size_r;
	
	POBJECT_HEAD oh;
	OBJECT_HEAD *pFoucsObj;
	PTEXT_FIELD pCtrl;
	PWINSTYLE  	lpWinSty;
	UINT32		fgColor;
	UINT8*		pStr;
	VSCR		*pGVscr;
	
	vscr_idx = osal_task_get_current_id();
	if((vscr_idx == OSAL_INVALID_ID) || (vscr_idx > OSD_DRAW_TASK_MAX))
		ASSERT(0);

	runner_obj_change_value+=1;
	if(runner_obj_change_value >=total_runner_obj_value)
		runner_obj_change_value=0;
	Get_OSD_TXT_Runner_Map(runner_obj_change_value,&osd_running_Obj);
	uoffset_xvalue=(osd_running_Obj.offset_value+osd_running_Obj.offset_step);
	obj_run_mode=osd_running_Obj.run_obj_mode;
	obj_run_total_strlen=osd_running_Obj.total_strlen;
	
	//Get_OSD_TXT_Runner_Obj(runner_obj_change_value,pFoucsObj);
	pFoucsObj=(OBJECT_HEAD *)Get_OSD_TXT_Runner_Obj(runner_obj_change_value);
	nCmdDraw=C_UPDATE_ALL;
#if 1
	drawType=C_DRAW_TYPE_NORMAL;


	//OSD_GetVscr(&pFoucsObj->frame, OSD_REQBUF); 
	bStyleIdx = pFoucsObj->style.bHLIdx;

	lpWinSty 	= g_osd_rsc_info.osd_get_win_style(bStyleIdx);
	fgColor		= lpWinSty->wBgIdx;
	
	pGVscr = OSD_GetVscr(&pFoucsObj->frame, OSD_REQBUF);
	OSD_DrawFrame(&pFoucsObj->frame,fgColor,pGVscr);
	//pGVscr->updatePending = 1;
	//OSD_UpdateVscr(&g_vscr[vscr_idx - 1]);
#endif
	bStyleIdx = pFoucsObj->style.bHLIdx;
	
	//OSD_DrawTextFieldCell_Ext(osd_running_Obj.run_head,bStyleIdx,nCmdDraw);
	OSD_DrawTextFieldCell_Ext((PTEXT_FIELD)pFoucsObj,bStyleIdx,nCmdDraw);
	if(g_vscr[vscr_idx - 1].lpbScr != NULL)
		g_vscr[vscr_idx - 1].updatePending = 1;
	
	OSD_UpdateVscr(&g_vscr[vscr_idx - 1]);
	Set_OSD_TXT_Runner_Offset_Value(runner_obj_change_value,uoffset_xvalue);
	
}

#endif

#ifdef PERSIAN_SUPPORT
//--------------------------------------------------------------------------------------------------
const unsigned short Arbic_Position_Index[]=/*first,last,midile,alone*/		
{
      	0x621,0x622,0x623,0x624,0x625,0x626,0x627,0x628,0x629,0x62A,0x62B,0x62C,0x62D,0x62E,0x62F,
	0x630,0x631,0x632,0x633,0x634,0x635,0x636,0x637,0x638,0x639,0x63A,0x63B,0x63C,0x63D,0x63E,0x63F,
	0x640,0x641,0x642,0x643,0x644,0x645,0x646,0x647,0x648,0x649,0x64A,//for arabic
	0x67E,0x686,0x698,0x6AF,0x6A9,		//for Persian 4 extended Char	
	0x06cc,		//Ben 140512#1
};
#define ARB_POS_INDX_NUM  (sizeof(Arbic_Position_Index)/sizeof(Arbic_Position_Index[0]))

const unsigned short Arbic_Convert_Order_Special_Ascii_Index[]=
{
//	0x22,0x20,//0x0D,0x0A,
	0xFEF5,0xFEF6,
	0xFEF7,0xFEF8,
	0xFEF9,0xFEFA,
	0xFEFB,0xFEFC,
	//add arabic digital number 0 1 2 3 4 5 6 7 8 9 
	0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39
};
#define ARB_COVT_ORD_SP_ASC_INDX	(sizeof(Arbic_Convert_Order_Special_Ascii_Index)/sizeof(Arbic_Convert_Order_Special_Ascii_Index[0]))

const unsigned short Arbic_Combing_Char_Index[8]=
{
	0xFEF5,0xFEF6,
	0xFEF7,0xFEF8,
	0xFEF9,0xFEFA,
	0xFEFB,0xFEFC,
};
#define ARB_COMB_CHAR_INDX	(sizeof(Arbic_Combing_Char_Index)/sizeof(Arbic_Combing_Char_Index[0]))

const unsigned short Arbic_Convert_Order_Special_Ascii_Punctuation_Index[]=
{
	0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
	0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
	0x40,
	0x5E,0x5F,0x60,
	0x7B,0x7C,0x7D,0x7E,
	0x60C,		//Ben 131127#2
};
#define ARB_COVT_ORD_SP_ASC_PUNC_INDX	(sizeof(Arbic_Convert_Order_Special_Ascii_Punctuation_Index)/sizeof(Arbic_Convert_Order_Special_Ascii_Punctuation_Index[0]))

const unsigned short Arbic_Position[][4]=/*last,first,midile,alone*/
{
       { 0xfe80,0xfe80,0xfe80, 0xfe80},/*0x0621*/
       { 0xfe82,0xfe81,0xfe82, 0xfe81},/*0x0622*/
       { 0xfe84, 0xfe83, 0xfe84, 0xfe83},/*0x0623*/
       { 0xfe86, 0xfe85, 0xfe86, 0xfe85},/*0x0624*/
       { 0xfe88, 0xfe87, 0xfe88, 0xfe87},/*0x0625*/
       { 0xfe8a, 0xfe8b, 0xfe8c, 0xfe89},/*0x0626*/
       { 0xfe8e, 0xfe8d, 0xfe8e, 0xfe8d},/*0x0627*/
       { 0xfe90, 0xfe91, 0xfe92, 0xfe8f},/*0x0628*/
       { 0xfe94, 0xfe93, 0xfe93, 0xfe93},/*0x0629*/
       { 0xfe96, 0xfe97, 0xfe98, 0xfe95},/*0x062A*/
       { 0xfe9a, 0xfe9b, 0xfe9c, 0xfe99},/*0x062B*/
       { 0xfe9e, 0xfe9f, 0xfea0, 0xfe9d},/*0x062C*/
       { 0xfea2, 0xfea3, 0xfea4, 0xfea1},/*0x062D*/
       { 0xfea6, 0xfea7, 0xfea8, 0xfea5},/*0x062E*/
       { 0xfeaa, 0xfea9, 0xfeaa, 0xfea9},/*0x062F*/
       { 0xfeac, 0xfeab, 0xfeac, 0xfeab},/*0x0630*/
       { 0xfeae, 0xfead, 0xfeae, 0xfead},/*0x0631*/
       { 0xfeb0, 0xfeaf, 0xfeb0, 0xfeaf},/*0x0632*/
       { 0xfeb2, 0xfeb3, 0xfeb4, 0xfeb1},/*0x0633*/
       { 0xfeb6, 0xfeb7, 0xfeb8, 0xfeb5},/*0x0634*/
       { 0xfeba, 0xfebb, 0xfebc, 0xfeb9},/*0x0635*/
       { 0xfebe, 0xfebf, 0xfec0, 0xfebd},/*0x0636*/
       { 0xfec2, 0xfec3, 0xfec4, 0xfec1},/*0x0637*/
       { 0xfec6, 0xfec7, 0xfec8, 0xfec5},/*0x0638*/
       { 0xfeca, 0xfecb, 0xfecc, 0xfec9},/*0x0639*/
       { 0xfece, 0xfecf, 0xfed0, 0xfecd},/*0x063A*/
       { 0x63b, 0x63b, 0x63b, 0x63b},		/*0x063B*/
       { 0x63c, 0x63c, 0x63c, 0x63c},		/*0x063C*/
       { 0x63d, 0x63d, 0x63d, 0x63d},		/*0x063D*/
       { 0x63e, 0x63e, 0x63e, 0x63e},		/*0x063E*/
       { 0x63f, 0x63f, 0x63f, 0x63f},		/*0x063F*/
       { 0x640, 0x640, 0x640, 0x640},		/*'-'*//*0x0640*/
       { 0xfed2, 0xfed3, 0xfed4, 0xfed1},/*0x0641*/
       { 0xfed6, 0xfed7, 0xfed8, 0xfed5},/*0x0642*/
       { 0xfeda, 0xfedb, 0xfedc, 0xfed9},/*0x0643*/
       { 0xfede, 0xfedf, 0xfee0, 0xfedd},/*0x0644*/
       { 0xfee2, 0xfee3, 0xfee4, 0xfee1},/*0x0645*/
       { 0xfee6, 0xfee7, 0xfee8, 0xfee5},/*0x0646*/
       { 0xfeea, 0xfeeb, 0xfeec, 0xfee9},/*0x0647*/
       { 0xfeee, 0xfeed, 0xfeee, 0xfeed},/*0x0648*/
       { 0xfef0, 0xfeef, 0xfef0, 0xfeef},/*0x0649*/
       { 0xfef2, 0xfef3, 0xfef4, 0xfef1}, /*0x064a*/
       
       { 0xFB57, 0xFB59, 0xFB59, 0xFB57},/*0x67E*/
	{ 0xFB7B, 0xFB7C, 0xFB7D, 0xFB7A,},/*0x686*/
       { 0xFB8B, 0x698  , 0xFB8B, 0x698},/*0x698*/
       { 0xFB93, 0xFB94, 0xFB95, 0x6AF},/*0x6AF*/	          
       { 0xFB8F, 0xFB90, 0xFB91, 0x6A9},/*0x6A9*/	 
       {0xfbfd, 0xfbfe, 0xfbff, 0xfbfc},   // 0x06cc		//Ben 140512#1
       //total 48...		
};

#if 0//for arabic
const unsigned short theSet1[23]={						//for Front link.---vision right
        0x62c, 0x62d, 0x62e, 0x647, 0x639, 0x63a, 0x641, 0x642,
        0x62b, 0x635, 0x636, 0x637, 0x643, 0x645, 0x646, 0x62a,
        0x644, 0x628, 0x64a, 0x633, 0x634, 0x638, 0x626
        };
const unsigned short theSet2[35]={						//for behind link.---vision Left
        0x62c, 0x62d, 0x62e, 0x647, 0x639, 0x63a, 0x641, 0x642,
        0x62b, 0x635, 0x636, 0x637, 0x643, 0x645, 0x646, 0x62a,
        0x644, 0x628, 0x64a, 0x633, 0x634, 0x638, 0x626,
        0x627, 0x623, 0x625, 0x622, 0x62f, 0x630, 0x631, 0x632,
        0x648, 0x624, 0x629, 0x649
        };
#else//for persian.
const unsigned short theSet1[]={						//for Front link.---vision left
        0x62c, 0x62d, 0x62e, 0x647, 0x639, 0x63a, 0x641, 0x642,
        0x62b, 0x635, 0x636, 0x637, 0x643, 0x645, 0x646, 0x62a,
        0x644, 0x628, 0x64a, 0x633, 0x634, 0x638, 0x626,
        0x627, 0x623, 0x625, 0x622, 0x62f, 0x630, 0x631, 0x632,
        0x648, 0x624, 0x629, 0x649, 0x640,
        0x67E, 0x686, 0x698, 0x6AF,0x6A9,//for persian
        0x6CC,	//Ben 140512#1
	0xFEF6,0xFEF8,0xFEFA,0xFEFC
        };
#define SET1_NUM	(sizeof(theSet1)/sizeof(theSet1[0]))


const unsigned short theSet2[]={						//for behind link.---vision right
        0x62c, 0x62d, 0x62e, 0x647, 0x639, 0x63a, 0x641, 0x642,
        0x62b, 0x635, 0x636, 0x637, 0x643, 0x645, 0x646, 0x62a,
        0x644, 0x628, 0x64a, 0x633, 0x634, 0x638, 0x626,
        /*0x622,*/ 0x623, 0x625,/* 0x627, 0x62f, 0x630, 0x631, 0x632,
        0x648,*/ 0x624, 0x629, 0x649,0x640,
        0x67E,0x686,  0x6AF,0x6A9,//for persian.    
        0x6CC,	//Ben 140512#1
        //0x698//for persian
        };
#define SET2_NUM	(sizeof(theSet2)/sizeof(theSet2[0]))

#endif
const unsigned short theSet3[]={0x622,0x623,0x625,0x627};
#define SET3_NUM	(sizeof(theSet3)/sizeof(theSet3[0]))

//Ben 140512#1
const unsigned short persian_extend[]={0x67E,0x686,0x698,0x6AF,0x6A9,0x6CC};//extend 4 char in persian support
#define PER_EX_NUM	(sizeof(persian_extend)/sizeof(persian_extend[0]))

//Ben 140512#1
const unsigned short persian_subscript[]={0x64B,0x64C,0x64D,0x64E,0x64F,0x650,0x651,0x652,};//extend 4 char in persian support
#define PER_SUB_NUM	(sizeof(persian_subscript)/sizeof(persian_subscript[0]))

const unsigned short arabic_specs[][2]=
{
	{0xFEF5,0xFEF6},
	{0xFEF7,0xFEF8},
	{0xFEF9,0xFEFA},
	{0xFEFB,0xFEFC},
};

//Ben 131127#1
//For ZERO WIDTH NON-JOINER
const unsigned short theZWNJSet[] = {0x200C};
#define ZWNJ_NUM	(sizeof(theZWNJSet)/sizeof(theZWNJSet[0]))
//

typedef struct Line_Information
{
	UINT8	Line_Number;
	UINT16	Start_Offset;
	UINT16	End_Offset;	
}LINE_INFO;
BOOL is_arabic_extend_set(unsigned short Unicode)
{
	if((Unicode<=0x6fe)&&(Unicode>=0x660)&&(Unicode!=0x698))
		return TRUE;
	else if((Unicode<=0x39)&&(Unicode>=0x30))//arabic digital num 0~9
		return TRUE;
	else
		return FALSE;
		
}
BOOL is_arabic_set(unsigned short Unicode,unsigned short* Set)
{
	INT16 SetLen=0,i=0;
	//SetLen=sizeof(Set)/2;
	if(Set==theSet1)
		SetLen=SET1_NUM;
	else if(Set==theSet2)
		SetLen=SET2_NUM;
	else if(Set==theSet3)
		SetLen=SET3_NUM;
	else if(Set==persian_extend)
		SetLen=PER_EX_NUM;
	else if(Set==Arbic_Position_Index)
		SetLen=ARB_POS_INDX_NUM;
	else if(Set==Arbic_Convert_Order_Special_Ascii_Index)
		SetLen=ARB_COVT_ORD_SP_ASC_INDX;
	else if(Set==Arbic_Convert_Order_Special_Ascii_Punctuation_Index)
		SetLen=ARB_COVT_ORD_SP_ASC_PUNC_INDX;
	else if(Set==Arbic_Combing_Char_Index)
		SetLen=ARB_COMB_CHAR_INDX;
	else if(Set==persian_subscript)
		SetLen=PER_SUB_NUM;
	//Ben 131127#1
	else if(Set==theZWNJSet)
		SetLen=ZWNJ_NUM;
	//Ben 131127#1
	//libc_printf("SetLen=%d \n",SetLen);		//Ben 140512#1
	
	while(i<SetLen)
	{
		if(Unicode==Set[i])
			return TRUE;
		i++;
	}
	return FALSE;
}

enum
{
    ENGLISH_ENV = 0,
#ifdef CHINESE_SUPPORT
    CHINESE_ENV,
#endif
    FRANCE_ENV,
    GERMANY_ENV ,
    ITALY_ENV,
    SPANISH_ENV,
    PORTUGUESE_ENV,
    RUSSIAN_ENV,
    TURKISH_ENV,
    POLISH_ENV,
    ARABIC_ENV,
#ifdef PERSIAN_SUPPORT
    PERSIAN_ENV,
#endif
    ENDLANG_ENV
};
static OSAL_ID xformer_cb_sem = OSAL_INVALID_ID;
void xformer_capture_semaphore(void)
{
   // return;

    if(xformer_cb_sem == OSAL_INVALID_ID)
        xformer_cb_sem = osal_semaphore_create(1);
    if(xformer_cb_sem != OSAL_INVALID_ID)
       osal_semaphore_capture(xformer_cb_sem,OSAL_WAIT_FOREVER_TIME);
}

void xformer_release_semaphore(void)
{
   // return;

    if(xformer_cb_sem != OSAL_INVALID_ID)
        osal_semaphore_release(xformer_cb_sem);
}
static UINT16	StrBak[1024]={0};

#define BUF_SEC  29
//#define PRNT_BUF

#if (1)	//Ben 131008#1
void arabic_unistr_xformer(unsigned short* UniStr,BOOL ConvertFlag,BOOL MB_flag)
{
	#define First		1////0
	#define Last		0///1
	#define Middle	2
	#define Alone	3
	
	//SYSTEM_DATA* p_sys_data;
	INT16	UniStrLen,i,j,XformerPos=0,connect_pos,k,m,n,temp,flag,t;	
	INT16 XformerPos_Array[4]={Alone,Last,First,Middle};//{Alone,First,Last,Middle};
	LINE_INFO  line_info[16];
	ID_RSC		RscId;

	//Ben 131127#1
	#ifdef PRNT_BUF
	UINT32 sub_time_bk = GetCurSubTime();	
	#endif
	//Ben 131127#1
	
	RscId=OSD_GetLangEnvironment();		
	if(RscId==PERSIAN_ENV||RscId==ARABIC_ENV)//for  arabic and persian .
	{		
		i=0;
		while(UniStr[i])
		{
			if(MB_flag)
				UniStr[i]=((UniStr[i]<<8)&0xFF00)|((UniStr[i]>>8)&0xFF);//MB to LB
			i++;
		}
		if(i==0)
			return;
		UniStrLen=i;		

		#ifdef PRNT_BUF
		if(BUF_SEC == sub_time_bk)
		{
			libc_printf("1 \n");
			libc_printf("%d buf: ",UniStrLen);
			for(i=0;i<UniStrLen;i++)
			{
				libc_printf("0x%04x ",UniStr[i]);
			}
			libc_printf(" \n");
		}
		#endif
		
		//if(UniStrLen>511)
		//	return;//do not transfer sftring for too long sub_string for some time.
		//for(i=0;i<1024;i++)
		//	StrBak[i]=0;
		//step1 : follow rule2-connecting	rule.		
		for(i=0,j=0;i<UniStrLen;i++)
		{	
			if(is_arabic_set(UniStr[i],(unsigned short *)persian_subscript))
			{
				continue;//eat subscript char.
			}
			else if(UniStr[i]==0x644)
			{
				if(is_arabic_set(UniStr[i+1],(unsigned short *)theSet3))
				{
					if(i)
					{
						if(is_arabic_set(UniStr[i-1],(unsigned short *)theSet2))
							connect_pos=1;
						else
							connect_pos=0;
					}
					else
							connect_pos=0;	
					k=0;
					while(1)
					{
						if(UniStr[i+1]==theSet3[k])
						break;
						k++;
					}
					//UniStr[512+j]=arabic_specs[k][connect_pos];//choose connecting Char to replace 2-combing chars
					StrBak[j]=arabic_specs[k][connect_pos];//choose connecting Char to replace 2-combing chars
					i++;
				}
				else
					//UniStr[512+j]=UniStr[i];//bak-copy unistr to 512B Address
					StrBak[j]=UniStr[i];//bak-copy unistr to 512B Address
			}			
			else
			{				
				//UniStr[512+j]=UniStr[i];//bak-copy unistr to 512B Address
				StrBak[j]=UniStr[i];//bak-copy unistr to 512B Address
			}
			j++;
		}
		if(j<UniStrLen)//copy back string after connecting form 512 to 0
		{
			for(i=0;i<=j;i++)
			{
				if(i==j)
				UniStr[i]=0;	//set NULL ending  flag			
				else	
				//UniStr[i]=UniStr[i+512];			
				UniStr[i]=StrBak[i];		
			}
		}	
		
		//step 2: follow rule 1--xformer rule.
		UniStrLen=j;

		#ifdef PRNT_BUF
		if(BUF_SEC == sub_time_bk)
		{
			libc_printf("2 \n");
			libc_printf("%d buf: ",UniStrLen);
			for(i=0;i<UniStrLen;i++)
			{
				libc_printf("0x%04x ",UniStr[i]);
			}
			libc_printf(" \n");
		}
		#endif
			//---------------------------------------------------------------------------------------
		#if 1	
		//3Convert continous Persian string except Standard Ascii string Uni-Bytes.
			//------------------------------------------------------------------------------
			for(i=0;i<16;i++)
			{
				line_info[i].Line_Number=0xFF;
				line_info[i].Start_Offset=line_info[i].End_Offset=0;
			}
			i=j=0;
			line_info[0].Line_Number=0;
			line_info[0].Start_Offset=0;
			line_info[0].End_Offset=0;
			while(i<UniStrLen)
			{
				if(UniStr[i]==0x0D&&UniStr[i+1]==0x0A)
				{
					line_info[j].Line_Number=j;
					line_info[j].End_Offset=i-1;
					j++;
					line_info[j].Line_Number=j;
					line_info[j].Start_Offset=i+2;
					i+=2;
				}
				else
					i++;				
			}
			line_info[j].End_Offset=UniStrLen-1;

			for(i=0;i<=j;i++)
			{
				k=line_info[i].Start_Offset;
				while(k<=line_info[i].End_Offset)
				{
					if((UniStr[k]>=0x60D/* 0x60B //Ben 131127#1*/&&UniStr[k]<=0x6fe)|| is_arabic_set(UniStr[k],(unsigned short *)Arbic_Combing_Char_Index))
					{
						line_info[i].Start_Offset=k;
						break;
					}	
					else
						k++;
				}
				if((k-1)!=line_info[i].End_Offset)//that means current line is include arabic/persian code.
				{
					k=line_info[i].End_Offset;
					while(k>line_info[i].Start_Offset)
					{						
						if((UniStr[k]>=0x60D/* 0x60B //Ben 131127#1*/&&UniStr[k]<=0x6fe)|| is_arabic_set(UniStr[k],(unsigned short *)Arbic_Combing_Char_Index))
						{
							line_info[i].End_Offset=k;
							break;							
						}
						else
							k--;
					}
					//convert arabic string segments
					k=line_info[i].Start_Offset;
					while(k<=line_info[i].End_Offset)
					{
						if((UniStr[k]>=0x60D/* 0x60B //Ben 131127#1*/&&UniStr[k]<=0x6fe)||
						    is_arabic_set(UniStr[k],(unsigned short *)Arbic_Convert_Order_Special_Ascii_Index)||
						    is_arabic_set(UniStr[k],(unsigned short *)theZWNJSet)||	/* //Ben 131127#1*/
						    is_arabic_set(UniStr[k],(unsigned short *)Arbic_Convert_Order_Special_Ascii_Punctuation_Index))
						{
							m=n=k;
							while((k<=line_info[i].End_Offset)&&((UniStr[k]>=0x60D/* 0x60B //Ben 131127#1*/&&UniStr[k]<=0x6fe)||
							    is_arabic_set(UniStr[k],(unsigned short *)Arbic_Convert_Order_Special_Ascii_Index)||
							    is_arabic_set(UniStr[k],(unsigned short *)theZWNJSet)||	/* //Ben 131127#1*/
							    is_arabic_set(UniStr[k],(unsigned short *)Arbic_Convert_Order_Special_Ascii_Punctuation_Index)))
							{
								n=k;
								k++;
							}
							for(t=m;t<(((n-m+1)>>1)+m);t++)
							{
								temp=UniStr[t];
								UniStr[t]=UniStr[n+m-t];
								UniStr[n+m-t]=temp;						
							}							
						}						
						else
							k++;
					}					
				}				
			}

		#ifdef PRNT_BUF
		if(BUF_SEC == sub_time_bk)
		{
			libc_printf("3 \n");
			libc_printf("%d buf: ",UniStrLen);
			for(i=0;i<UniStrLen;i++)
			{
				libc_printf("0x%04x ",UniStr[i]);
			}
			libc_printf(" \n");
		}
		#endif
		
			//------------------------------------------------------------------------------				
		//3when exit multi line string,that means "0x000D,0x000A"	must be set as milestones for each line that it converts each line by. 
		//3so we should do something as below to finish the converting. 
		if(ConvertFlag)
		{
			i=0;
			j=k=0;
			while(i<UniStrLen)
			{
				if(UniStr[i]==0x0D&&UniStr[i+1]==0x0A)
				{		
					k=i-1;
					for(m=j;m<=k;m++)
					{					
						temp=m-j;
						//UniStr[512+UniStrLen-i+temp]=UniStr[m];
						StrBak[UniStrLen-i+temp]=UniStr[m];
					}
					//UniStr[512+UniStrLen-i-1]=0x0A;
					//UniStr[512+UniStrLen-i-2]=0x0D;
					StrBak[UniStrLen-i-1]=0x0A;
					StrBak[UniStrLen-i-2]=0x0D;				
					j=i+2;
					i+=2;
				}
				else
				{
					i++;
				}	
			}
			for(m=0;m<(UniStrLen-j);m++)
			{
				//UniStr[512+m]=UniStr[j+m];
				StrBak[m]=UniStr[j+m];
			}
			//copy back from address 512 to 0
			for(i=0;i<UniStrLen;i++)
			{
				//UniStr[i]=UniStr[i+512];			
				UniStr[i]=StrBak[i];	
			}
		}	
		#endif

		#ifdef PRNT_BUF
		if(BUF_SEC == sub_time_bk)
		{
			libc_printf("4 \n");
			libc_printf("%d buf: ",UniStrLen);
			for(i=0;i<UniStrLen;i++)
			{
				libc_printf("0x%04x ",UniStr[i]);
			}
			libc_printf(" \n");
		}
		#endif
		
		//---------------------------------------------------------------------------------------		
//		for(i=0;i<UniStrLen;i++)CharDebug[i]=UniStr[i];			
		for(i=0;i<UniStrLen;i++)
		{ 
			if((UniStr[i]>=0x621&&UniStr[i]<=0x64A)||is_arabic_set(UniStr[i],(unsigned short *)persian_extend))
			{
				if(i==0)
				{
					if(is_arabic_set(UniStr[i+1],(unsigned short *)theSet2)||is_arabic_extend_set(UniStr[i+1]))
						XformerPos = Last; 
					else
						XformerPos = Alone; 
				}
				else if(i<=UniStrLen-2)
				{
					temp=0;
					if(is_arabic_set(UniStr[i-1],(unsigned short *)theSet1)||is_arabic_extend_set(UniStr[i-1]))
						temp |= 0x02;//0x02;
					if(is_arabic_set(UniStr[i+1],(unsigned short *)theSet2)||is_arabic_extend_set(UniStr[i+1]))
						temp |= 0x01;//0x01;
					//XformerPos:0--Alone		 1--Last 		2--First		3--Middle
					XformerPos=XformerPos_Array[temp];
				}
				else if(i==UniStrLen-1)
				{
					if(is_arabic_set(UniStr[i-1],(unsigned short *)theSet1)||is_arabic_extend_set(UniStr[i-1]))
						XformerPos = First; 
					else
						XformerPos = Alone; 
				}
//				CharDebug[i]|=(XformerPos<<12);
				//j=UniStr[i]-0x621;
					j=0;
					while(1)//calculate char index
					{
						if(UniStr[i]==Arbic_Position_Index[j])
						break;
						j++;
					}
				//UniStr[i+512]=Arbic_Position[j][XformerPos];
				StrBak[i]=Arbic_Position[j][XformerPos];
			}		
			else
			{
				//UniStr[i+512]=UniStr[i];
				StrBak[i]=UniStr[i];
			}
		}
		for(i=0;i<UniStrLen;i++)
		{			
			UniStr[i]=StrBak[i];
			if(MB_flag)
			UniStr[i]=((UniStr[i]<<8)&0xFF00)|((UniStr[i]>>8)&0xFF);//MB to LB
		}	

		#ifdef PRNT_BUF
		if(BUF_SEC == sub_time_bk)
		{
			libc_printf("5 \n");
			libc_printf("%d buf: ",UniStrLen);
			for(i=0;i<UniStrLen;i++)
			{
				libc_printf("0x%04x ",UniStr[i]);
			}
			libc_printf(" \n");
		}
		#endif
		
		//Ben 131127#1
		k=0;
		for(i=0;i<UniStrLen;i++)
		{
			if(is_arabic_set(UniStr[i],(unsigned short *)theZWNJSet))
			{
				for(j=i; j<UniStrLen; j++)
				{
					UniStr[j] = UniStr[j+1];
				}
				k++;
			}
		}
		UniStrLen -= k;
		//Ben 131127#1

		#ifdef PRNT_BUF
		if(BUF_SEC == sub_time_bk)
		{
			libc_printf("5.1 \n");
			libc_printf("%d buf: ",UniStrLen);
			for(i=0;i<UniStrLen;i++)
			{
				libc_printf("0x%04x ",UniStr[i]);
			}
			libc_printf(" \n");
		}		
		#endif
		
//		for(i=0;i<UniStrLen;i++)CharDebug[i+256]=UniStr[i];			
		if(ConvertFlag)//this flag depending on direction of OSD show
		{
			for(i=0;i<(UniStrLen>>1);i++)
			{			
				k=UniStr[i];
				UniStr[i]=UniStr[UniStrLen-i-1];
				UniStr[UniStrLen-i-1]=k;
			}	
		}

		#ifdef PRNT_BUF
		if(BUF_SEC == sub_time_bk)
		{
			libc_printf("6 \n");
			libc_printf("%d buf: ",UniStrLen);
			for(i=0;i<UniStrLen;i++)
			{
				libc_printf("0x%04x ",UniStr[i]);
			}
			libc_printf(" \n");
		}
		#endif
	}
	#undef First
	#undef Last
	#undef Middle
	#undef Alone
}
#else
extern BOOL sub_flag;
void arabic_unistr_xformer(unsigned short* UniStr,BOOL ConvertFlag,BOOL MB_flag)
{
	UINT32 i,j,k,LineOffset,Cur_Line_Words;
	BOOL switch_line_fg,is_sub_str_fg;
	UINT16	UniTmp;
	ID_RSC		RscId;
	RscId=OSD_GetLangEnvironment();		
	if(RscId==PERSIAN_ENV||RscId==ARABIC_ENV)//for  arabic and persian .
	{	
		//--judge if the string is include original persian string.
		/*
		i=j=0;
		while(UniStr[j])
		{
			i++;
			if(!(UniStr[j]>=0x60B&&UniStr[j]<=0x6fe))
				j++;
		}	
		if(i==j)return;*/
		//--------		
		i=0;
		j=0;
		while(UniStr[i])
		{
			if(MB_flag)
				UniStr[i]=((UniStr[i]<<8)&0xFF00)|((UniStr[i]>>8)&0xFF);//MB to LB
			StrBak[i]=UniStr[i];	
			i++;
			if(!(UniStr[j]>=0x60B&&UniStr[j]<=0x6fe))
				j++;
		}
		StrBak[i]=0x0;		
		if(!i)return;
		if(i==j)
			goto NOT_PROCESS;

		//2step1: unify 0x0D,0x0A to 0x0
		is_sub_str_fg = FALSE;
		for(j=0;j<=i;j++)
		{
			if(StrBak[j]==0x0D||StrBak[j]==0x0A)
			{
				is_sub_str_fg = TRUE;
				StrBak[j]=0;		
			}									
		}
		//2step2: process persian string line by line
		LineOffset = 0;
		switch_line_fg = TRUE;
		for(j=0;j<=i;j++)
		{
			if(StrBak[j]==0 && switch_line_fg)
			{
				sub_flag = TRUE;
				//Ben 131008#1
				//persian_process(StrBak+LineOffset,j-LineOffset);
				persian_process_mp(StrBak+LineOffset,j-LineOffset);
				//Ben 131008#1
				sub_flag	= FALSE;
				if(ConvertFlag)
				{	
					//start
					//re-cacaulate cur line words					
					Cur_Line_Words=j-LineOffset;
					k=0;
					while(StrBak[j-k-1]==0x0)
					{
						Cur_Line_Words--;
						k++;
					}	
					k=0;
					//end
					while(k<(Cur_Line_Words/2))
					{
						UniTmp = StrBak[LineOffset+k] ;
						StrBak[LineOffset+k] = StrBak[LineOffset+Cur_Line_Words-1-k]; 
						StrBak[LineOffset+Cur_Line_Words-1-k] = UniTmp;
						k++;
					}
				}
				switch_line_fg = FALSE;
			}
			else
			{
				if(StrBak[j]!=0 && !switch_line_fg)
				{
					LineOffset = j;
					switch_line_fg = TRUE;
				}	
			}		
		}
		//2step3: copyback persian string after processing
		switch_line_fg = FALSE;
		for(j=0,k=0;j<=i;j++)
		{		
			if(StrBak[j]!=0)
			{
				UniStr[k++]=StrBak[j];
				switch_line_fg = FALSE;
			}	
			else
			{
				if(!switch_line_fg&is_sub_str_fg)
				{
					UniStr[k++]=0x0A;			
					switch_line_fg = TRUE;	
				}
			}	
		}
		UniStr[k]=0x0;

		//2step4: MB.LB restore.
NOT_PROCESS:
		i=0;
		while(UniStr[i])
		{
			if(MB_flag)
				UniStr[i]=((UniStr[i]<<8)&0xFF00)|((UniStr[i]>>8)&0xFF);//MB to LB
			i++;
		}	
		
	}	
}
#endif
//--------------------------------------------------------------------------------------------------
#endif

